Merge "Code cleanup on NMPS and NMS." into nyc-dev
diff --git a/Android.mk b/Android.mk
index 2ee7600..3ac5889 100644
--- a/Android.mk
+++ b/Android.mk
@@ -150,14 +150,14 @@
core/java/android/content/pm/IPackageStatsObserver.aidl \
core/java/android/content/pm/IOnPermissionsChangeListener.aidl \
core/java/android/database/IContentObserver.aidl \
- core/java/android/hardware/ICameraService.aidl \
- core/java/android/hardware/ICameraServiceListener.aidl \
- core/java/android/hardware/ICameraServiceProxy.aidl \
- core/java/android/hardware/ICamera.aidl \
- core/java/android/hardware/ICameraClient.aidl \
+ ../av/camera/aidl/android/hardware/ICameraService.aidl \
+ ../av/camera/aidl/android/hardware/ICameraServiceListener.aidl \
+ ../av/camera/aidl/android/hardware/ICameraServiceProxy.aidl \
+ ../av/camera/aidl/android/hardware/ICamera.aidl \
+ ../av/camera/aidl/android/hardware/ICameraClient.aidl \
+ ../av/camera/aidl/android/hardware/camera2/ICameraDeviceUser.aidl \
+ ../av/camera/aidl/android/hardware/camera2/ICameraDeviceCallbacks.aidl \
core/java/android/hardware/IConsumerIrService.aidl \
- core/java/android/hardware/camera2/ICameraDeviceUser.aidl \
- core/java/android/hardware/camera2/ICameraDeviceCallbacks.aidl \
core/java/android/hardware/ISerialManager.aidl \
core/java/android/hardware/display/IDisplayManager.aidl \
core/java/android/hardware/display/IDisplayManagerCallback.aidl \
@@ -455,6 +455,10 @@
$(FRAMEWORKS_BASE_JAVA_SRC_DIRS) \
frameworks/native/aidl/binder
+LOCAL_AIDL_INCLUDES += \
+ frameworks/av/camera/aidl \
+ frameworks/native/aidl/gui
+
LOCAL_INTERMEDIATE_SOURCES := \
$(framework_res_source_path)/android/R.java \
$(framework_res_source_path)/android/Manifest.java \
@@ -577,7 +581,7 @@
frameworks/base/core/java/android/view/Display.aidl \
frameworks/base/core/java/android/view/InputDevice.aidl \
frameworks/base/core/java/android/view/InputEvent.aidl \
- frameworks/base/core/java/android/view/Surface.aidl \
+ frameworks/native/aidl/gui/android/view/Surface.aidl \
frameworks/base/core/java/android/view/WindowContentFrameStats.aidl \
frameworks/base/core/java/android/view/inputmethod/InputMethodSubtype.aidl \
frameworks/base/core/java/android/view/inputmethod/CursorAnchorInfo.aidl \
diff --git a/CleanSpec.mk b/CleanSpec.mk
index 2fe5cbe..cee8fdb 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -240,6 +240,7 @@
$(call add-clean-step, rm -f $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/media/java/android/media/IRemoteControlDisplay.*)
$(call add-clean-step, rm -f $(OUT_DIR)/target/common/obj/APPS/FeatureSplit1_intermediates/src/com/android/test/split/feature/R.java)
$(call add-clean-step, rm -f $(OUT_DIR)/target/common/obj/APPS/FeatureSplit2_intermediates/src/com/android/test/split/feature/R.java)
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core/java/android/hardware)
# ******************************************************************
# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST ABOVE THIS BANNER
diff --git a/api/current.txt b/api/current.txt
index 2f57d9a..73e7fab 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -2668,6 +2668,8 @@
field public static final int GLOBAL_ACTION_TOGGLE_SPLIT_SCREEN = 7; // 0x7
field public static final java.lang.String SERVICE_INTERFACE = "android.accessibilityservice.AccessibilityService";
field public static final java.lang.String SERVICE_META_DATA = "android.accessibilityservice";
+ field public static final int SHOW_MODE_AUTO = 0; // 0x0
+ field public static final int SHOW_MODE_HIDDEN = 1; // 0x1
}
public static abstract class AccessibilityService.GestureResultCallback {
@@ -5608,8 +5610,6 @@
method public void enableCarMode(int);
method public int getCurrentModeType();
method public int getNightMode();
- method public boolean isNightModeLocked();
- method public boolean isUiModeLocked();
method public void setNightMode(int);
field public static java.lang.String ACTION_ENTER_CAR_MODE;
field public static java.lang.String ACTION_ENTER_DESK_MODE;
@@ -5711,6 +5711,7 @@
public class WallpaperManager {
method public void clear() throws java.io.IOException;
+ method public void clear(int) throws java.io.IOException;
method public void clearWallpaperOffsets(android.os.IBinder);
method public void forgetLoadedWallpaper();
method public android.graphics.drawable.Drawable getBuiltInDrawable();
@@ -19155,168 +19156,110 @@
public final class GnssClock implements android.os.Parcelable {
method public int describeContents();
- method public double getBiasInNs();
- method public double getBiasUncertaintyInNs();
- method public double getDriftInNsPerSec();
- method public double getDriftUncertaintyInNsPerSec();
- method public long getFullBiasInNs();
+ method public double getBiasNanos();
+ method public double getBiasUncertaintyNanos();
+ method public double getDriftNanosPerSecond();
+ method public double getDriftUncertaintyNanosPerSecond();
+ method public long getFullBiasNanos();
method public int getHardwareClockDiscontinuityCount();
- method public short getLeapSecond();
- method public long getTimeInNs();
- method public double getTimeUncertaintyInNs();
- method public boolean hasBiasInNs();
- method public boolean hasBiasUncertaintyInNs();
- method public boolean hasDriftInNsPerSec();
- method public boolean hasDriftUncertaintyInNsPerSec();
- method public boolean hasFullBiasInNs();
+ method public int getLeapSecond();
+ method public long getTimeNanos();
+ method public double getTimeUncertaintyNanos();
+ method public boolean hasBiasNanos();
+ method public boolean hasBiasUncertaintyNanos();
+ method public boolean hasDriftNanosPerSecond();
+ method public boolean hasDriftUncertaintyNanosPerSecond();
+ method public boolean hasFullBiasNanos();
method public boolean hasLeapSecond();
- method public boolean hasTimeUncertaintyInNs();
+ method public boolean hasTimeUncertaintyNanos();
method public void reset();
- method public void resetBiasInNs();
- method public void resetBiasUncertaintyInNs();
- method public void resetDriftInNsPerSec();
- method public void resetDriftUncertaintyInNsPerSec();
- method public void resetFullBiasInNs();
+ method public void resetBiasNanos();
+ method public void resetBiasUncertaintyNanos();
+ method public void resetDriftNanosPerSecond();
+ method public void resetDriftUncertaintyNanosPerSecond();
+ method public void resetFullBiasNanos();
method public void resetLeapSecond();
- method public void resetTimeUncertaintyInNs();
+ method public void resetTimeUncertaintyNanos();
method public void set(android.location.GnssClock);
- method public void setBiasInNs(double);
- method public void setBiasUncertaintyInNs(double);
- method public void setDriftInNsPerSec(double);
- method public void setDriftUncertaintyInNsPerSec(double);
- method public void setFullBiasInNs(long);
+ method public void setBiasNanos(double);
+ method public void setBiasUncertaintyNanos(double);
+ method public void setDriftNanosPerSecond(double);
+ method public void setDriftUncertaintyNanosPerSecond(double);
+ method public void setFullBiasNanos(long);
method public void setHardwareClockDiscontinuityCount(int);
- method public void setLeapSecond(short);
- method public void setTimeInNs(long);
- method public void setTimeUncertaintyInNs(double);
+ method public void setLeapSecond(int);
+ method public void setTimeNanos(long);
+ method public void setTimeUncertaintyNanos(double);
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.location.GnssClock> CREATOR;
}
public final class GnssMeasurement implements android.os.Parcelable {
method public int describeContents();
- method public double getAccumulatedDeltaRangeInMeters();
- method public short getAccumulatedDeltaRangeState();
- method public double getAccumulatedDeltaRangeUncertaintyInMeters();
- method public double getAzimuthInDeg();
- method public double getAzimuthUncertaintyInDeg();
- method public int getBitNumber();
+ method public double getAccumulatedDeltaRangeMeters();
+ method public int getAccumulatedDeltaRangeState();
+ method public double getAccumulatedDeltaRangeUncertaintyMeters();
method public long getCarrierCycles();
- method public float getCarrierFrequencyInHz();
+ method public float getCarrierFrequencyHz();
method public double getCarrierPhase();
method public double getCarrierPhaseUncertainty();
- method public double getCn0InDbHz();
- method public double getCodePhaseInChips();
- method public double getCodePhaseUncertaintyInChips();
- method public byte getConstellationType();
- method public double getDopplerShiftInHz();
- method public double getDopplerShiftUncertaintyInHz();
- method public double getElevationInDeg();
- method public double getElevationUncertaintyInDeg();
- method public byte getLossOfLock();
- method public byte getMultipathIndicator();
- method public double getPseudorangeInMeters();
- method public double getPseudorangeRateInMetersPerSec();
- method public double getPseudorangeRateUncertaintyInMetersPerSec();
- method public double getPseudorangeUncertaintyInMeters();
- method public long getReceivedSvTimeInNs();
- method public long getReceivedSvTimeUncertaintyInNs();
+ method public double getCn0DbHz();
+ method public int getConstellationType();
+ method public int getMultipathIndicator();
+ method public double getPseudorangeRateMetersPerSecond();
+ method public double getPseudorangeRateUncertaintyMetersPerSecond();
+ method public long getReceivedSvTimeNanos();
+ method public long getReceivedSvTimeUncertaintyNanos();
method public double getSnrInDb();
- method public short getState();
- method public short getSvid();
- method public short getTimeFromLastBitInMs();
- method public double getTimeOffsetInNs();
- method public boolean hasAzimuthInDeg();
- method public boolean hasAzimuthUncertaintyInDeg();
- method public boolean hasBitNumber();
+ method public int getState();
+ method public int getSvid();
+ method public double getTimeOffsetNanos();
method public boolean hasCarrierCycles();
- method public boolean hasCarrierFrequencyInHz();
+ method public boolean hasCarrierFrequencyHz();
method public boolean hasCarrierPhase();
method public boolean hasCarrierPhaseUncertainty();
- method public boolean hasCodePhaseInChips();
- method public boolean hasCodePhaseUncertaintyInChips();
- method public boolean hasDopplerShiftInHz();
- method public boolean hasDopplerShiftUncertaintyInHz();
- method public boolean hasElevationInDeg();
- method public boolean hasElevationUncertaintyInDeg();
- method public boolean hasPseudorangeInMeters();
- method public boolean hasPseudorangeUncertaintyInMeters();
method public boolean hasSnrInDb();
- method public boolean hasTimeFromLastBitInMs();
method public boolean isPseudorangeRateCorrected();
- method public boolean isUsedInFix();
method public void reset();
- method public void resetAzimuthInDeg();
- method public void resetAzimuthUncertaintyInDeg();
- method public void resetBitNumber();
method public void resetCarrierCycles();
- method public void resetCarrierFrequencyInHz();
+ method public void resetCarrierFrequencyHz();
method public void resetCarrierPhase();
method public void resetCarrierPhaseUncertainty();
- method public void resetCodePhaseInChips();
- method public void resetCodePhaseUncertaintyInChips();
- method public void resetDopplerShiftInHz();
- method public void resetDopplerShiftUncertaintyInHz();
- method public void resetElevationInDeg();
- method public void resetElevationUncertaintyInDeg();
- method public void resetPseudorangeInMeters();
- method public void resetPseudorangeUncertaintyInMeters();
method public void resetSnrInDb();
- method public void resetTimeFromLastBitInMs();
method public void set(android.location.GnssMeasurement);
- method public void setAccumulatedDeltaRangeInMeters(double);
- method public void setAccumulatedDeltaRangeState(short);
- method public void setAccumulatedDeltaRangeUncertaintyInMeters(double);
- method public void setAzimuthInDeg(double);
- method public void setAzimuthUncertaintyInDeg(double);
- method public void setBitNumber(int);
+ method public void setAccumulatedDeltaRangeMeters(double);
+ method public void setAccumulatedDeltaRangeState(int);
+ method public void setAccumulatedDeltaRangeUncertaintyMeters(double);
method public void setCarrierCycles(long);
- method public void setCarrierFrequencyInHz(float);
+ method public void setCarrierFrequencyHz(float);
method public void setCarrierPhase(double);
method public void setCarrierPhaseUncertainty(double);
- method public void setCn0InDbHz(double);
- method public void setCodePhaseInChips(double);
- method public void setCodePhaseUncertaintyInChips(double);
- method public void setConstellationType(byte);
- method public void setDopplerShiftInHz(double);
- method public void setDopplerShiftUncertaintyInHz(double);
- method public void setElevationInDeg(double);
- method public void setElevationUncertaintyInDeg(double);
- method public void setLossOfLock(byte);
- method public void setMultipathIndicator(byte);
- method public void setPseudorangeInMeters(double);
- method public void setPseudorangeRateInMetersPerSec(double);
- method public void setPseudorangeRateUncertaintyInMetersPerSec(double);
- method public void setPseudorangeUncertaintyInMeters(double);
- method public void setReceivedSvTimeInNs(long);
- method public void setReceivedSvTimeUncertaintyInNs(long);
+ method public void setCn0DbHz(double);
+ method public void setConstellationType(int);
+ method public void setMultipathIndicator(int);
+ method public void setPseudorangeRateMetersPerSecond(double);
+ method public void setPseudorangeRateUncertaintyMetersPerSecond(double);
+ method public void setReceivedSvTimeNanos(long);
+ method public void setReceivedSvTimeUncertaintyNanos(long);
method public void setSnrInDb(double);
- method public void setState(short);
- method public void setSvid(short);
- method public void setTimeFromLastBitInMs(short);
- method public void setTimeOffsetInNs(double);
- method public void setUsedInFix(boolean);
+ method public void setState(int);
+ method public void setSvid(int);
+ method public void setTimeOffsetNanos(double);
method public void writeToParcel(android.os.Parcel, int);
- field public static final short ADR_STATE_CYCLE_SLIP = 4; // 0x4
- field public static final short ADR_STATE_RESET = 2; // 0x2
- field public static final short ADR_STATE_UNKNOWN = 0; // 0x0
- field public static final short ADR_STATE_VALID = 1; // 0x1
+ field public static final int ADR_STATE_CYCLE_SLIP = 4; // 0x4
+ field public static final int ADR_STATE_RESET = 2; // 0x2
+ field public static final int ADR_STATE_UNKNOWN = 0; // 0x0
+ field public static final int ADR_STATE_VALID = 1; // 0x1
field public static final android.os.Parcelable.Creator<android.location.GnssMeasurement> CREATOR;
- field public static final byte LOSS_OF_LOCK_CYCLE_SLIP = 2; // 0x2
- field public static final byte LOSS_OF_LOCK_OK = 1; // 0x1
- field public static final byte LOSS_OF_LOCK_UNKNOWN = 0; // 0x0
- field public static final byte MULTIPATH_INDICATOR_DETECTED = 1; // 0x1
- field public static final byte MULTIPATH_INDICATOR_NOT_USED = 2; // 0x2
- field public static final byte MULTIPATH_INDICATOR_UNKNOWN = 0; // 0x0
- field public static final short STATE_BIT_SYNC = 2; // 0x2
- field public static final short STATE_CODE_LOCK = 1; // 0x1
- field public static final short STATE_MSEC_AMBIGUOUS = 16; // 0x10
- field public static final short STATE_SUBFRAME_SYNC = 4; // 0x4
- field public static final short STATE_TOW_DECODED = 8; // 0x8
- field public static final short STATE_UNKNOWN = 0; // 0x0
- }
-
- public static abstract class GnssMeasurement.LossOfLockStatus implements java.lang.annotation.Annotation {
+ field public static final int MULTIPATH_INDICATOR_DETECTED = 1; // 0x1
+ field public static final int MULTIPATH_INDICATOR_NOT_USED = 2; // 0x2
+ field public static final int MULTIPATH_INDICATOR_UNKNOWN = 0; // 0x0
+ field public static final int STATE_BIT_SYNC = 2; // 0x2
+ field public static final int STATE_CODE_LOCK = 1; // 0x1
+ field public static final int STATE_MSEC_AMBIGUOUS = 16; // 0x10
+ field public static final int STATE_SUBFRAME_SYNC = 4; // 0x4
+ field public static final int STATE_TOW_DECODED = 8; // 0x8
+ field public static final int STATE_UNKNOWN = 0; // 0x0
}
public static abstract class GnssMeasurement.MultipathIndicator implements java.lang.annotation.Annotation {
@@ -19329,7 +19272,7 @@
method public java.util.Collection<android.location.GnssMeasurement> getMeasurements();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.location.GnssMeasurementsEvent> CREATOR;
- field public static final int STATUS_GPS_LOCATION_DISABLED = 2; // 0x2
+ field public static final int STATUS_GNSS_LOCATION_DISABLED = 2; // 0x2
field public static final int STATUS_NOT_SUPPORTED = 0; // 0x0
field public static final int STATUS_READY = 1; // 0x1
}
@@ -19346,34 +19289,34 @@
public final class GnssNavigationMessage implements android.os.Parcelable {
method public int describeContents();
method public byte[] getData();
- method public short getMessageId();
- method public short getStatus();
- method public short getSubmessageId();
- method public short getSvid();
- method public short getType();
+ method public int getMessageId();
+ method public int getStatus();
+ method public int getSubmessageId();
+ method public int getSvid();
+ method public int getType();
method public void reset();
method public void set(android.location.GnssNavigationMessage);
method public void setData(byte[]);
- method public void setMessageId(short);
- method public void setStatus(short);
- method public void setSubmessageId(short);
- method public void setSvid(short);
- method public void setType(short);
+ method public void setMessageId(int);
+ method public void setStatus(int);
+ method public void setSubmessageId(int);
+ method public void setSvid(int);
+ method public void setType(int);
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.location.GnssNavigationMessage> CREATOR;
- field public static final short MESSAGE_TYPE_BDS_D1 = 1281; // 0x501
- field public static final short MESSAGE_TYPE_BDS_D2 = 1282; // 0x502
- field public static final short MESSAGE_TYPE_GAL_F = 1538; // 0x602
- field public static final short MESSAGE_TYPE_GAL_I = 1537; // 0x601
- field public static final short MESSAGE_TYPE_GLO_L1CA = 769; // 0x301
- field public static final short MESSAGE_TYPE_GPS_CNAV2 = 260; // 0x104
- field public static final short MESSAGE_TYPE_GPS_L1CA = 257; // 0x101
- field public static final short MESSAGE_TYPE_GPS_L2CNAV = 258; // 0x102
- field public static final short MESSAGE_TYPE_GPS_L5CNAV = 259; // 0x103
- field public static final short MESSAGE_TYPE_UNKNOWN = 0; // 0x0
- field public static final short STATUS_PARITY_PASSED = 1; // 0x1
- field public static final short STATUS_PARITY_REBUILT = 2; // 0x2
- field public static final short STATUS_UNKNOWN = 0; // 0x0
+ field public static final int STATUS_PARITY_PASSED = 1; // 0x1
+ field public static final int STATUS_PARITY_REBUILT = 2; // 0x2
+ field public static final int STATUS_UNKNOWN = 0; // 0x0
+ field public static final int TYPE_BDS_D1 = 1281; // 0x501
+ field public static final int TYPE_BDS_D2 = 1282; // 0x502
+ field public static final int TYPE_GAL_F = 1538; // 0x602
+ field public static final int TYPE_GAL_I = 1537; // 0x601
+ field public static final int TYPE_GLO_L1CA = 769; // 0x301
+ field public static final int TYPE_GPS_CNAV2 = 260; // 0x104
+ field public static final int TYPE_GPS_L1CA = 257; // 0x101
+ field public static final int TYPE_GPS_L2CNAV = 258; // 0x102
+ field public static final int TYPE_GPS_L5CNAV = 259; // 0x103
+ field public static final int TYPE_UNKNOWN = 0; // 0x0
}
public static abstract class GnssNavigationMessage.GnssNavigationMessageType implements java.lang.annotation.Annotation {
@@ -19385,7 +19328,7 @@
method public android.location.GnssNavigationMessage getNavigationMessage();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.location.GnssNavigationMessageEvent> CREATOR;
- field public static final int STATUS_GPS_LOCATION_DISABLED = 2; // 0x2
+ field public static final int STATUS_GNSS_LOCATION_DISABLED = 2; // 0x2
field public static final int STATUS_NOT_SUPPORTED = 0; // 0x0
field public static final int STATUS_READY = 1; // 0x1
}
@@ -19404,22 +19347,22 @@
}
public final class GnssStatus {
- method public float getAzimuth(int);
- method public byte getConstellationType(int);
- method public float getElevation(int);
+ method public float getAzimuthDegrees(int);
+ method public float getCn0DbHz(int);
+ method public int getConstellationType(int);
+ method public float getElevationDegrees(int);
method public int getNumSatellites();
- method public float getSnr(int);
method public int getSvid(int);
method public boolean hasAlmanac(int);
method public boolean hasEphemeris(int);
method public boolean usedInFix(int);
- field public static final byte CONSTELLATION_BEIDOU = 5; // 0x5
- field public static final byte CONSTELLATION_GALILEO = 6; // 0x6
- field public static final byte CONSTELLATION_GLONASS = 3; // 0x3
- field public static final byte CONSTELLATION_GPS = 1; // 0x1
- field public static final byte CONSTELLATION_QZSS = 4; // 0x4
- field public static final byte CONSTELLATION_SBAS = 2; // 0x2
- field public static final byte CONSTELLATION_UNKNOWN = 0; // 0x0
+ field public static final int CONSTELLATION_BEIDOU = 5; // 0x5
+ field public static final int CONSTELLATION_GALILEO = 6; // 0x6
+ field public static final int CONSTELLATION_GLONASS = 3; // 0x3
+ field public static final int CONSTELLATION_GPS = 1; // 0x1
+ field public static final int CONSTELLATION_QZSS = 4; // 0x4
+ field public static final int CONSTELLATION_SBAS = 2; // 0x2
+ field public static final int CONSTELLATION_UNKNOWN = 0; // 0x0
}
public static abstract class GnssStatus.ConstellationType implements java.lang.annotation.Annotation {
@@ -19534,8 +19477,8 @@
method public java.util.List<java.lang.String> getProviders(boolean);
method public java.util.List<java.lang.String> getProviders(android.location.Criteria, boolean);
method public boolean isProviderEnabled(java.lang.String);
- method public boolean registerGnssMeasurementCallback(android.location.GnssMeasurementsEvent.Callback);
- method public boolean registerGnssMeasurementCallback(android.location.GnssMeasurementsEvent.Callback, android.os.Handler);
+ method public boolean registerGnssMeasurementsCallback(android.location.GnssMeasurementsEvent.Callback);
+ method public boolean registerGnssMeasurementsCallback(android.location.GnssMeasurementsEvent.Callback, android.os.Handler);
method public boolean registerGnssNavigationMessageCallback(android.location.GnssNavigationMessageEvent.Callback);
method public boolean registerGnssNavigationMessageCallback(android.location.GnssNavigationMessageEvent.Callback, android.os.Handler);
method public boolean registerGnssStatusCallback(android.location.GnssStatusCallback);
@@ -19560,7 +19503,7 @@
method public void setTestProviderEnabled(java.lang.String, boolean);
method public void setTestProviderLocation(java.lang.String, android.location.Location);
method public void setTestProviderStatus(java.lang.String, int, android.os.Bundle, long);
- method public void unregisterGnssMeasurementCallback(android.location.GnssMeasurementsEvent.Callback);
+ method public void unregisterGnssMeasurementsCallback(android.location.GnssMeasurementsEvent.Callback);
method public void unregisterGnssNavigationMessageCallback(android.location.GnssNavigationMessageEvent.Callback);
method public void unregisterGnssStatusCallback(android.location.GnssStatusCallback);
field public static final java.lang.String GPS_PROVIDER = "gps";
@@ -20992,6 +20935,7 @@
field public static final java.lang.String KEY_SLICE_HEIGHT = "slice-height";
field public static final java.lang.String KEY_STRIDE = "stride";
field public static final java.lang.String KEY_TEMPORAL_LAYERING = "ts-schema";
+ field public static final java.lang.String KEY_TRACK_ID = "track-id";
field public static final java.lang.String KEY_WIDTH = "width";
field public static final java.lang.String MIMETYPE_AUDIO_AAC = "audio/mp4a-latm";
field public static final java.lang.String MIMETYPE_AUDIO_AC3 = "audio/ac3";
@@ -29104,6 +29048,8 @@
ctor public Process();
method public static final long getElapsedCpuTime();
method public static final int getGidForName(java.lang.String);
+ method public static final long getStartElapsedRealtime();
+ method public static final long getStartUptimeMillis();
method public static final int getThreadPriority(int) throws java.lang.IllegalArgumentException;
method public static final int getUidForName(java.lang.String);
method public static final boolean is64Bit();
@@ -34291,7 +34237,8 @@
ctor public CarrierMessagingService();
method public android.os.IBinder onBind(android.content.Intent);
method public void onDownloadMms(android.net.Uri, int, android.net.Uri, android.service.carrier.CarrierMessagingService.ResultCallback<java.lang.Integer>);
- method public void onFilterSms(android.service.carrier.MessagePdu, java.lang.String, int, int, android.service.carrier.CarrierMessagingService.ResultCallback<java.lang.Boolean>);
+ method public deprecated void onFilterSms(android.service.carrier.MessagePdu, java.lang.String, int, int, android.service.carrier.CarrierMessagingService.ResultCallback<java.lang.Boolean>);
+ method public void onReceiveTextSms(android.service.carrier.MessagePdu, java.lang.String, int, int, android.service.carrier.CarrierMessagingService.ResultCallback<java.lang.Integer>);
method public deprecated void onSendDataSms(byte[], int, java.lang.String, int, android.service.carrier.CarrierMessagingService.ResultCallback<android.service.carrier.CarrierMessagingService.SendSmsResult>);
method public void onSendDataSms(byte[], int, java.lang.String, int, int, android.service.carrier.CarrierMessagingService.ResultCallback<android.service.carrier.CarrierMessagingService.SendSmsResult>);
method public void onSendMms(android.net.Uri, int, android.net.Uri, android.service.carrier.CarrierMessagingService.ResultCallback<android.service.carrier.CarrierMessagingService.SendMmsResult>);
@@ -34302,6 +34249,9 @@
field public static final int DOWNLOAD_STATUS_ERROR = 2; // 0x2
field public static final int DOWNLOAD_STATUS_OK = 0; // 0x0
field public static final int DOWNLOAD_STATUS_RETRY_ON_CARRIER_NETWORK = 1; // 0x1
+ field public static final int RECEIVE_OPTIONS_DEFAULT = 0; // 0x0
+ field public static final int RECEIVE_OPTIONS_DROP = 1; // 0x1
+ field public static final int RECEIVE_OPTIONS_SKIP_NOTIFY_WHEN_CREDENTIAL_ENCRYPTED_STORAGE_UNAVAILABLE = 2; // 0x2
field public static final int SEND_FLAG_REQUEST_DELIVERY_STATUS = 1; // 0x1
field public static final int SEND_STATUS_ERROR = 2; // 0x2
field public static final int SEND_STATUS_OK = 0; // 0x0
@@ -40140,6 +40090,7 @@
method public int describeContents();
method public static android.util.LocaleList forLanguageTags(java.lang.String);
method public java.util.Locale get(int);
+ method public static android.util.LocaleList getAdjustedDefault();
method public static android.util.LocaleList getDefault();
method public static android.util.LocaleList getEmptyLocaleList();
method public java.util.Locale getFirstMatch(java.lang.String[]);
@@ -50451,6 +50402,7 @@
method public static long doubleToRawLongBits(double);
method public double doubleValue();
method public float floatValue();
+ method public static int hashCode(double);
method public int intValue();
method public static boolean isInfinite(double);
method public boolean isInfinite();
@@ -50458,11 +50410,15 @@
method public boolean isNaN();
method public static double longBitsToDouble(long);
method public long longValue();
+ method public static double max(double, double);
+ method public static double min(double, double);
method public static double parseDouble(java.lang.String) throws java.lang.NumberFormatException;
+ method public static double sum(double, double);
method public static java.lang.String toHexString(double);
method public static java.lang.String toString(double);
method public static java.lang.Double valueOf(java.lang.String) throws java.lang.NumberFormatException;
method public static java.lang.Double valueOf(double);
+ field public static final int BYTES = 8; // 0x8
field public static final int MAX_EXPONENT = 1023; // 0x3ff
field public static final double MAX_VALUE = 1.7976931348623157E308;
field public static final int MIN_EXPONENT = -1022; // 0xfffffc02
@@ -50625,10 +50581,13 @@
method public static java.lang.Integer getInteger(java.lang.String);
method public static java.lang.Integer getInteger(java.lang.String, int);
method public static java.lang.Integer getInteger(java.lang.String, java.lang.Integer);
+ method public static int hashCode(int);
method public static int highestOneBit(int);
method public int intValue();
method public long longValue();
method public static int lowestOneBit(int);
+ method public static int max(int, int);
+ method public static int min(int, int);
method public static int numberOfLeadingZeros(int);
method public static int numberOfTrailingZeros(int);
method public static int parseInt(java.lang.String, int) throws java.lang.NumberFormatException;
@@ -50638,6 +50597,7 @@
method public static int rotateLeft(int, int);
method public static int rotateRight(int, int);
method public static int signum(int);
+ method public static int sum(int, int);
method public static java.lang.String toBinaryString(int);
method public static java.lang.String toHexString(int);
method public static java.lang.String toOctalString(int);
@@ -50646,6 +50606,7 @@
method public static java.lang.Integer valueOf(java.lang.String, int) throws java.lang.NumberFormatException;
method public static java.lang.Integer valueOf(java.lang.String) throws java.lang.NumberFormatException;
method public static java.lang.Integer valueOf(int);
+ field public static final int BYTES = 4; // 0x4
field public static final int MAX_VALUE = 2147483647; // 0x7fffffff
field public static final int MIN_VALUE = -2147483648; // 0x80000000
field public static final int SIZE = 32; // 0x20
@@ -50687,10 +50648,13 @@
method public static java.lang.Long getLong(java.lang.String);
method public static java.lang.Long getLong(java.lang.String, long);
method public static java.lang.Long getLong(java.lang.String, java.lang.Long);
+ method public static int hashCode(long);
method public static long highestOneBit(long);
method public int intValue();
method public long longValue();
method public static long lowestOneBit(long);
+ method public static long max(long, long);
+ method public static long min(long, long);
method public static int numberOfLeadingZeros(long);
method public static int numberOfTrailingZeros(long);
method public static long parseLong(java.lang.String, int) throws java.lang.NumberFormatException;
@@ -50700,6 +50664,7 @@
method public static long rotateLeft(long, int);
method public static long rotateRight(long, int);
method public static int signum(long);
+ method public static long sum(long, long);
method public static java.lang.String toBinaryString(long);
method public static java.lang.String toHexString(long);
method public static java.lang.String toOctalString(long);
@@ -58054,6 +58019,54 @@
method public abstract void update(java.util.Observable, java.lang.Object);
}
+ public final class Optional {
+ method public static java.util.Optional<T> empty();
+ method public java.util.Optional<T> filter(java.util.function.Predicate<? super T>);
+ method public java.util.Optional<U> flatMap(java.util.function.Function<? super T, java.util.Optional<U>>);
+ method public T get();
+ method public void ifPresent(java.util.function.Consumer<? super T>);
+ method public boolean isPresent();
+ method public java.util.Optional<U> map(java.util.function.Function<? super T, ? extends U>);
+ method public static java.util.Optional<T> of(T);
+ method public static java.util.Optional<T> ofNullable(T);
+ method public T orElse(T);
+ method public T orElseGet(java.util.function.Supplier<? extends T>);
+ method public T orElseThrow(java.util.function.Supplier<? extends X>) throws java.lang.Throwable;
+ }
+
+ public final class OptionalDouble {
+ method public static java.util.OptionalDouble empty();
+ method public double getAsDouble();
+ method public void ifPresent(java.util.function.DoubleConsumer);
+ method public boolean isPresent();
+ method public static java.util.OptionalDouble of(double);
+ method public double orElse(double);
+ method public double orElseGet(java.util.function.DoubleSupplier);
+ method public double orElseThrow(java.util.function.Supplier<X>) throws java.lang.Throwable;
+ }
+
+ public final class OptionalInt {
+ method public static java.util.OptionalInt empty();
+ method public int getAsInt();
+ method public void ifPresent(java.util.function.IntConsumer);
+ method public boolean isPresent();
+ method public static java.util.OptionalInt of(int);
+ method public int orElse(int);
+ method public int orElseGet(java.util.function.IntSupplier);
+ method public int orElseThrow(java.util.function.Supplier<X>) throws java.lang.Throwable;
+ }
+
+ public final class OptionalLong {
+ method public static java.util.OptionalLong empty();
+ method public long getAsLong();
+ method public void ifPresent(java.util.function.LongConsumer);
+ method public boolean isPresent();
+ method public static java.util.OptionalLong of(long);
+ method public long orElse(long);
+ method public long orElseGet(java.util.function.LongSupplier);
+ method public long orElseThrow(java.util.function.Supplier<X>) throws java.lang.Throwable;
+ }
+
public class PriorityQueue extends java.util.AbstractQueue implements java.io.Serializable {
ctor public PriorityQueue();
ctor public PriorityQueue(int);
diff --git a/api/system-current.txt b/api/system-current.txt
index 03e261b..e5ebe62 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -2770,6 +2770,8 @@
field public static final int GLOBAL_ACTION_TOGGLE_SPLIT_SCREEN = 7; // 0x7
field public static final java.lang.String SERVICE_INTERFACE = "android.accessibilityservice.AccessibilityService";
field public static final java.lang.String SERVICE_META_DATA = "android.accessibilityservice";
+ field public static final int SHOW_MODE_AUTO = 0; // 0x0
+ field public static final int SHOW_MODE_HIDDEN = 1; // 0x1
}
public static abstract class AccessibilityService.GestureResultCallback {
@@ -5740,8 +5742,6 @@
method public void enableCarMode(int);
method public int getCurrentModeType();
method public int getNightMode();
- method public boolean isNightModeLocked();
- method public boolean isUiModeLocked();
method public void setNightMode(int);
field public static java.lang.String ACTION_ENTER_CAR_MODE;
field public static java.lang.String ACTION_ENTER_DESK_MODE;
@@ -5843,6 +5843,7 @@
public class WallpaperManager {
method public void clear() throws java.io.IOException;
+ method public void clear(int) throws java.io.IOException;
method public void clearWallpaper();
method public void clearWallpaper(int, int);
method public void clearWallpaperOffsets(android.os.IBinder);
@@ -9926,6 +9927,7 @@
method public android.graphics.drawable.Drawable loadIcon(android.content.pm.PackageManager);
method public java.lang.CharSequence loadLabel(android.content.pm.PackageManager);
method public android.graphics.drawable.Drawable loadLogo(android.content.pm.PackageManager);
+ method public java.lang.CharSequence loadSafeLabel(android.content.pm.PackageManager);
method public android.graphics.drawable.Drawable loadUnbadgedIcon(android.content.pm.PackageManager);
method public android.content.res.XmlResourceParser loadXmlMetaData(android.content.pm.PackageManager, java.lang.String);
method public void writeToParcel(android.os.Parcel, int);
@@ -10184,6 +10186,8 @@
field public static final int INSTALL_PARSE_FAILED_NO_CERTIFICATES = -103; // 0xffffff99
field public static final int INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION = -102; // 0xffffff9a
field public static final int INSTALL_SUCCEEDED = 1; // 0x1
+ field public static final int INTENT_FILTER_VERIFICATION_FAILURE = -1; // 0xffffffff
+ field public static final int INTENT_FILTER_VERIFICATION_SUCCESS = 1; // 0x1
field public static final int MASK_PERMISSION_FLAGS = 255; // 0xff
field public static final int MATCH_ALL = 131072; // 0x20000
field public static final int MATCH_DEFAULT_ONLY = 65536; // 0x10000
@@ -20325,168 +20329,110 @@
public final class GnssClock implements android.os.Parcelable {
method public int describeContents();
- method public double getBiasInNs();
- method public double getBiasUncertaintyInNs();
- method public double getDriftInNsPerSec();
- method public double getDriftUncertaintyInNsPerSec();
- method public long getFullBiasInNs();
+ method public double getBiasNanos();
+ method public double getBiasUncertaintyNanos();
+ method public double getDriftNanosPerSecond();
+ method public double getDriftUncertaintyNanosPerSecond();
+ method public long getFullBiasNanos();
method public int getHardwareClockDiscontinuityCount();
- method public short getLeapSecond();
- method public long getTimeInNs();
- method public double getTimeUncertaintyInNs();
- method public boolean hasBiasInNs();
- method public boolean hasBiasUncertaintyInNs();
- method public boolean hasDriftInNsPerSec();
- method public boolean hasDriftUncertaintyInNsPerSec();
- method public boolean hasFullBiasInNs();
+ method public int getLeapSecond();
+ method public long getTimeNanos();
+ method public double getTimeUncertaintyNanos();
+ method public boolean hasBiasNanos();
+ method public boolean hasBiasUncertaintyNanos();
+ method public boolean hasDriftNanosPerSecond();
+ method public boolean hasDriftUncertaintyNanosPerSecond();
+ method public boolean hasFullBiasNanos();
method public boolean hasLeapSecond();
- method public boolean hasTimeUncertaintyInNs();
+ method public boolean hasTimeUncertaintyNanos();
method public void reset();
- method public void resetBiasInNs();
- method public void resetBiasUncertaintyInNs();
- method public void resetDriftInNsPerSec();
- method public void resetDriftUncertaintyInNsPerSec();
- method public void resetFullBiasInNs();
+ method public void resetBiasNanos();
+ method public void resetBiasUncertaintyNanos();
+ method public void resetDriftNanosPerSecond();
+ method public void resetDriftUncertaintyNanosPerSecond();
+ method public void resetFullBiasNanos();
method public void resetLeapSecond();
- method public void resetTimeUncertaintyInNs();
+ method public void resetTimeUncertaintyNanos();
method public void set(android.location.GnssClock);
- method public void setBiasInNs(double);
- method public void setBiasUncertaintyInNs(double);
- method public void setDriftInNsPerSec(double);
- method public void setDriftUncertaintyInNsPerSec(double);
- method public void setFullBiasInNs(long);
+ method public void setBiasNanos(double);
+ method public void setBiasUncertaintyNanos(double);
+ method public void setDriftNanosPerSecond(double);
+ method public void setDriftUncertaintyNanosPerSecond(double);
+ method public void setFullBiasNanos(long);
method public void setHardwareClockDiscontinuityCount(int);
- method public void setLeapSecond(short);
- method public void setTimeInNs(long);
- method public void setTimeUncertaintyInNs(double);
+ method public void setLeapSecond(int);
+ method public void setTimeNanos(long);
+ method public void setTimeUncertaintyNanos(double);
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.location.GnssClock> CREATOR;
}
public final class GnssMeasurement implements android.os.Parcelable {
method public int describeContents();
- method public double getAccumulatedDeltaRangeInMeters();
- method public short getAccumulatedDeltaRangeState();
- method public double getAccumulatedDeltaRangeUncertaintyInMeters();
- method public double getAzimuthInDeg();
- method public double getAzimuthUncertaintyInDeg();
- method public int getBitNumber();
+ method public double getAccumulatedDeltaRangeMeters();
+ method public int getAccumulatedDeltaRangeState();
+ method public double getAccumulatedDeltaRangeUncertaintyMeters();
method public long getCarrierCycles();
- method public float getCarrierFrequencyInHz();
+ method public float getCarrierFrequencyHz();
method public double getCarrierPhase();
method public double getCarrierPhaseUncertainty();
- method public double getCn0InDbHz();
- method public double getCodePhaseInChips();
- method public double getCodePhaseUncertaintyInChips();
- method public byte getConstellationType();
- method public double getDopplerShiftInHz();
- method public double getDopplerShiftUncertaintyInHz();
- method public double getElevationInDeg();
- method public double getElevationUncertaintyInDeg();
- method public byte getLossOfLock();
- method public byte getMultipathIndicator();
- method public double getPseudorangeInMeters();
- method public double getPseudorangeRateInMetersPerSec();
- method public double getPseudorangeRateUncertaintyInMetersPerSec();
- method public double getPseudorangeUncertaintyInMeters();
- method public long getReceivedSvTimeInNs();
- method public long getReceivedSvTimeUncertaintyInNs();
+ method public double getCn0DbHz();
+ method public int getConstellationType();
+ method public int getMultipathIndicator();
+ method public double getPseudorangeRateMetersPerSecond();
+ method public double getPseudorangeRateUncertaintyMetersPerSecond();
+ method public long getReceivedSvTimeNanos();
+ method public long getReceivedSvTimeUncertaintyNanos();
method public double getSnrInDb();
- method public short getState();
- method public short getSvid();
- method public short getTimeFromLastBitInMs();
- method public double getTimeOffsetInNs();
- method public boolean hasAzimuthInDeg();
- method public boolean hasAzimuthUncertaintyInDeg();
- method public boolean hasBitNumber();
+ method public int getState();
+ method public int getSvid();
+ method public double getTimeOffsetNanos();
method public boolean hasCarrierCycles();
- method public boolean hasCarrierFrequencyInHz();
+ method public boolean hasCarrierFrequencyHz();
method public boolean hasCarrierPhase();
method public boolean hasCarrierPhaseUncertainty();
- method public boolean hasCodePhaseInChips();
- method public boolean hasCodePhaseUncertaintyInChips();
- method public boolean hasDopplerShiftInHz();
- method public boolean hasDopplerShiftUncertaintyInHz();
- method public boolean hasElevationInDeg();
- method public boolean hasElevationUncertaintyInDeg();
- method public boolean hasPseudorangeInMeters();
- method public boolean hasPseudorangeUncertaintyInMeters();
method public boolean hasSnrInDb();
- method public boolean hasTimeFromLastBitInMs();
method public boolean isPseudorangeRateCorrected();
- method public boolean isUsedInFix();
method public void reset();
- method public void resetAzimuthInDeg();
- method public void resetAzimuthUncertaintyInDeg();
- method public void resetBitNumber();
method public void resetCarrierCycles();
- method public void resetCarrierFrequencyInHz();
+ method public void resetCarrierFrequencyHz();
method public void resetCarrierPhase();
method public void resetCarrierPhaseUncertainty();
- method public void resetCodePhaseInChips();
- method public void resetCodePhaseUncertaintyInChips();
- method public void resetDopplerShiftInHz();
- method public void resetDopplerShiftUncertaintyInHz();
- method public void resetElevationInDeg();
- method public void resetElevationUncertaintyInDeg();
- method public void resetPseudorangeInMeters();
- method public void resetPseudorangeUncertaintyInMeters();
method public void resetSnrInDb();
- method public void resetTimeFromLastBitInMs();
method public void set(android.location.GnssMeasurement);
- method public void setAccumulatedDeltaRangeInMeters(double);
- method public void setAccumulatedDeltaRangeState(short);
- method public void setAccumulatedDeltaRangeUncertaintyInMeters(double);
- method public void setAzimuthInDeg(double);
- method public void setAzimuthUncertaintyInDeg(double);
- method public void setBitNumber(int);
+ method public void setAccumulatedDeltaRangeMeters(double);
+ method public void setAccumulatedDeltaRangeState(int);
+ method public void setAccumulatedDeltaRangeUncertaintyMeters(double);
method public void setCarrierCycles(long);
- method public void setCarrierFrequencyInHz(float);
+ method public void setCarrierFrequencyHz(float);
method public void setCarrierPhase(double);
method public void setCarrierPhaseUncertainty(double);
- method public void setCn0InDbHz(double);
- method public void setCodePhaseInChips(double);
- method public void setCodePhaseUncertaintyInChips(double);
- method public void setConstellationType(byte);
- method public void setDopplerShiftInHz(double);
- method public void setDopplerShiftUncertaintyInHz(double);
- method public void setElevationInDeg(double);
- method public void setElevationUncertaintyInDeg(double);
- method public void setLossOfLock(byte);
- method public void setMultipathIndicator(byte);
- method public void setPseudorangeInMeters(double);
- method public void setPseudorangeRateInMetersPerSec(double);
- method public void setPseudorangeRateUncertaintyInMetersPerSec(double);
- method public void setPseudorangeUncertaintyInMeters(double);
- method public void setReceivedSvTimeInNs(long);
- method public void setReceivedSvTimeUncertaintyInNs(long);
+ method public void setCn0DbHz(double);
+ method public void setConstellationType(int);
+ method public void setMultipathIndicator(int);
+ method public void setPseudorangeRateMetersPerSecond(double);
+ method public void setPseudorangeRateUncertaintyMetersPerSecond(double);
+ method public void setReceivedSvTimeNanos(long);
+ method public void setReceivedSvTimeUncertaintyNanos(long);
method public void setSnrInDb(double);
- method public void setState(short);
- method public void setSvid(short);
- method public void setTimeFromLastBitInMs(short);
- method public void setTimeOffsetInNs(double);
- method public void setUsedInFix(boolean);
+ method public void setState(int);
+ method public void setSvid(int);
+ method public void setTimeOffsetNanos(double);
method public void writeToParcel(android.os.Parcel, int);
- field public static final short ADR_STATE_CYCLE_SLIP = 4; // 0x4
- field public static final short ADR_STATE_RESET = 2; // 0x2
- field public static final short ADR_STATE_UNKNOWN = 0; // 0x0
- field public static final short ADR_STATE_VALID = 1; // 0x1
+ field public static final int ADR_STATE_CYCLE_SLIP = 4; // 0x4
+ field public static final int ADR_STATE_RESET = 2; // 0x2
+ field public static final int ADR_STATE_UNKNOWN = 0; // 0x0
+ field public static final int ADR_STATE_VALID = 1; // 0x1
field public static final android.os.Parcelable.Creator<android.location.GnssMeasurement> CREATOR;
- field public static final byte LOSS_OF_LOCK_CYCLE_SLIP = 2; // 0x2
- field public static final byte LOSS_OF_LOCK_OK = 1; // 0x1
- field public static final byte LOSS_OF_LOCK_UNKNOWN = 0; // 0x0
- field public static final byte MULTIPATH_INDICATOR_DETECTED = 1; // 0x1
- field public static final byte MULTIPATH_INDICATOR_NOT_USED = 2; // 0x2
- field public static final byte MULTIPATH_INDICATOR_UNKNOWN = 0; // 0x0
- field public static final short STATE_BIT_SYNC = 2; // 0x2
- field public static final short STATE_CODE_LOCK = 1; // 0x1
- field public static final short STATE_MSEC_AMBIGUOUS = 16; // 0x10
- field public static final short STATE_SUBFRAME_SYNC = 4; // 0x4
- field public static final short STATE_TOW_DECODED = 8; // 0x8
- field public static final short STATE_UNKNOWN = 0; // 0x0
- }
-
- public static abstract class GnssMeasurement.LossOfLockStatus implements java.lang.annotation.Annotation {
+ field public static final int MULTIPATH_INDICATOR_DETECTED = 1; // 0x1
+ field public static final int MULTIPATH_INDICATOR_NOT_USED = 2; // 0x2
+ field public static final int MULTIPATH_INDICATOR_UNKNOWN = 0; // 0x0
+ field public static final int STATE_BIT_SYNC = 2; // 0x2
+ field public static final int STATE_CODE_LOCK = 1; // 0x1
+ field public static final int STATE_MSEC_AMBIGUOUS = 16; // 0x10
+ field public static final int STATE_SUBFRAME_SYNC = 4; // 0x4
+ field public static final int STATE_TOW_DECODED = 8; // 0x8
+ field public static final int STATE_UNKNOWN = 0; // 0x0
}
public static abstract class GnssMeasurement.MultipathIndicator implements java.lang.annotation.Annotation {
@@ -20499,7 +20445,7 @@
method public java.util.Collection<android.location.GnssMeasurement> getMeasurements();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.location.GnssMeasurementsEvent> CREATOR;
- field public static final int STATUS_GPS_LOCATION_DISABLED = 2; // 0x2
+ field public static final int STATUS_GNSS_LOCATION_DISABLED = 2; // 0x2
field public static final int STATUS_NOT_SUPPORTED = 0; // 0x0
field public static final int STATUS_READY = 1; // 0x1
}
@@ -20516,34 +20462,34 @@
public final class GnssNavigationMessage implements android.os.Parcelable {
method public int describeContents();
method public byte[] getData();
- method public short getMessageId();
- method public short getStatus();
- method public short getSubmessageId();
- method public short getSvid();
- method public short getType();
+ method public int getMessageId();
+ method public int getStatus();
+ method public int getSubmessageId();
+ method public int getSvid();
+ method public int getType();
method public void reset();
method public void set(android.location.GnssNavigationMessage);
method public void setData(byte[]);
- method public void setMessageId(short);
- method public void setStatus(short);
- method public void setSubmessageId(short);
- method public void setSvid(short);
- method public void setType(short);
+ method public void setMessageId(int);
+ method public void setStatus(int);
+ method public void setSubmessageId(int);
+ method public void setSvid(int);
+ method public void setType(int);
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.location.GnssNavigationMessage> CREATOR;
- field public static final short MESSAGE_TYPE_BDS_D1 = 1281; // 0x501
- field public static final short MESSAGE_TYPE_BDS_D2 = 1282; // 0x502
- field public static final short MESSAGE_TYPE_GAL_F = 1538; // 0x602
- field public static final short MESSAGE_TYPE_GAL_I = 1537; // 0x601
- field public static final short MESSAGE_TYPE_GLO_L1CA = 769; // 0x301
- field public static final short MESSAGE_TYPE_GPS_CNAV2 = 260; // 0x104
- field public static final short MESSAGE_TYPE_GPS_L1CA = 257; // 0x101
- field public static final short MESSAGE_TYPE_GPS_L2CNAV = 258; // 0x102
- field public static final short MESSAGE_TYPE_GPS_L5CNAV = 259; // 0x103
- field public static final short MESSAGE_TYPE_UNKNOWN = 0; // 0x0
- field public static final short STATUS_PARITY_PASSED = 1; // 0x1
- field public static final short STATUS_PARITY_REBUILT = 2; // 0x2
- field public static final short STATUS_UNKNOWN = 0; // 0x0
+ field public static final int STATUS_PARITY_PASSED = 1; // 0x1
+ field public static final int STATUS_PARITY_REBUILT = 2; // 0x2
+ field public static final int STATUS_UNKNOWN = 0; // 0x0
+ field public static final int TYPE_BDS_D1 = 1281; // 0x501
+ field public static final int TYPE_BDS_D2 = 1282; // 0x502
+ field public static final int TYPE_GAL_F = 1538; // 0x602
+ field public static final int TYPE_GAL_I = 1537; // 0x601
+ field public static final int TYPE_GLO_L1CA = 769; // 0x301
+ field public static final int TYPE_GPS_CNAV2 = 260; // 0x104
+ field public static final int TYPE_GPS_L1CA = 257; // 0x101
+ field public static final int TYPE_GPS_L2CNAV = 258; // 0x102
+ field public static final int TYPE_GPS_L5CNAV = 259; // 0x103
+ field public static final int TYPE_UNKNOWN = 0; // 0x0
}
public static abstract class GnssNavigationMessage.GnssNavigationMessageType implements java.lang.annotation.Annotation {
@@ -20555,7 +20501,7 @@
method public android.location.GnssNavigationMessage getNavigationMessage();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.location.GnssNavigationMessageEvent> CREATOR;
- field public static final int STATUS_GPS_LOCATION_DISABLED = 2; // 0x2
+ field public static final int STATUS_GNSS_LOCATION_DISABLED = 2; // 0x2
field public static final int STATUS_NOT_SUPPORTED = 0; // 0x0
field public static final int STATUS_READY = 1; // 0x1
}
@@ -20574,22 +20520,22 @@
}
public final class GnssStatus {
- method public float getAzimuth(int);
- method public byte getConstellationType(int);
- method public float getElevation(int);
+ method public float getAzimuthDegrees(int);
+ method public float getCn0DbHz(int);
+ method public int getConstellationType(int);
+ method public float getElevationDegrees(int);
method public int getNumSatellites();
- method public float getSnr(int);
method public int getSvid(int);
method public boolean hasAlmanac(int);
method public boolean hasEphemeris(int);
method public boolean usedInFix(int);
- field public static final byte CONSTELLATION_BEIDOU = 5; // 0x5
- field public static final byte CONSTELLATION_GALILEO = 6; // 0x6
- field public static final byte CONSTELLATION_GLONASS = 3; // 0x3
- field public static final byte CONSTELLATION_GPS = 1; // 0x1
- field public static final byte CONSTELLATION_QZSS = 4; // 0x4
- field public static final byte CONSTELLATION_SBAS = 2; // 0x2
- field public static final byte CONSTELLATION_UNKNOWN = 0; // 0x0
+ field public static final int CONSTELLATION_BEIDOU = 5; // 0x5
+ field public static final int CONSTELLATION_GALILEO = 6; // 0x6
+ field public static final int CONSTELLATION_GLONASS = 3; // 0x3
+ field public static final int CONSTELLATION_GPS = 1; // 0x1
+ field public static final int CONSTELLATION_QZSS = 4; // 0x4
+ field public static final int CONSTELLATION_SBAS = 2; // 0x2
+ field public static final int CONSTELLATION_UNKNOWN = 0; // 0x0
}
public static abstract class GnssStatus.ConstellationType implements java.lang.annotation.Annotation {
@@ -20951,8 +20897,8 @@
method public java.util.List<java.lang.String> getProviders(boolean);
method public java.util.List<java.lang.String> getProviders(android.location.Criteria, boolean);
method public boolean isProviderEnabled(java.lang.String);
- method public boolean registerGnssMeasurementCallback(android.location.GnssMeasurementsEvent.Callback);
- method public boolean registerGnssMeasurementCallback(android.location.GnssMeasurementsEvent.Callback, android.os.Handler);
+ method public boolean registerGnssMeasurementsCallback(android.location.GnssMeasurementsEvent.Callback);
+ method public boolean registerGnssMeasurementsCallback(android.location.GnssMeasurementsEvent.Callback, android.os.Handler);
method public boolean registerGnssNavigationMessageCallback(android.location.GnssNavigationMessageEvent.Callback);
method public boolean registerGnssNavigationMessageCallback(android.location.GnssNavigationMessageEvent.Callback, android.os.Handler);
method public boolean registerGnssStatusCallback(android.location.GnssStatusCallback);
@@ -20981,7 +20927,7 @@
method public void setTestProviderEnabled(java.lang.String, boolean);
method public void setTestProviderLocation(java.lang.String, android.location.Location);
method public void setTestProviderStatus(java.lang.String, int, android.os.Bundle, long);
- method public void unregisterGnssMeasurementCallback(android.location.GnssMeasurementsEvent.Callback);
+ method public void unregisterGnssMeasurementsCallback(android.location.GnssMeasurementsEvent.Callback);
method public void unregisterGnssNavigationMessageCallback(android.location.GnssNavigationMessageEvent.Callback);
method public void unregisterGnssStatusCallback(android.location.GnssStatusCallback);
field public static final java.lang.String GPS_PROVIDER = "gps";
@@ -22481,6 +22427,7 @@
field public static final java.lang.String KEY_SLICE_HEIGHT = "slice-height";
field public static final java.lang.String KEY_STRIDE = "stride";
field public static final java.lang.String KEY_TEMPORAL_LAYERING = "ts-schema";
+ field public static final java.lang.String KEY_TRACK_ID = "track-id";
field public static final java.lang.String KEY_WIDTH = "width";
field public static final java.lang.String MIMETYPE_AUDIO_AAC = "audio/mp4a-latm";
field public static final java.lang.String MIMETYPE_AUDIO_AC3 = "audio/ac3";
@@ -26718,7 +26665,6 @@
method public boolean reconnect();
method public boolean removeNetwork(int);
method public boolean saveConfiguration();
- method public boolean setMetered(int, boolean);
method public void setTdlsEnabled(java.net.InetAddress, boolean);
method public void setTdlsEnabledWithMacAddress(java.lang.String, boolean);
method public boolean setWifiApConfiguration(android.net.wifi.WifiConfiguration);
@@ -31395,6 +31341,8 @@
ctor public Process();
method public static final long getElapsedCpuTime();
method public static final int getGidForName(java.lang.String);
+ method public static final long getStartElapsedRealtime();
+ method public static final long getStartUptimeMillis();
method public static final int getThreadPriority(int) throws java.lang.IllegalArgumentException;
method public static final int getUidForName(java.lang.String);
method public static final boolean is64Bit();
@@ -36779,7 +36727,8 @@
ctor public CarrierMessagingService();
method public android.os.IBinder onBind(android.content.Intent);
method public void onDownloadMms(android.net.Uri, int, android.net.Uri, android.service.carrier.CarrierMessagingService.ResultCallback<java.lang.Integer>);
- method public void onFilterSms(android.service.carrier.MessagePdu, java.lang.String, int, int, android.service.carrier.CarrierMessagingService.ResultCallback<java.lang.Boolean>);
+ method public deprecated void onFilterSms(android.service.carrier.MessagePdu, java.lang.String, int, int, android.service.carrier.CarrierMessagingService.ResultCallback<java.lang.Boolean>);
+ method public void onReceiveTextSms(android.service.carrier.MessagePdu, java.lang.String, int, int, android.service.carrier.CarrierMessagingService.ResultCallback<java.lang.Integer>);
method public deprecated void onSendDataSms(byte[], int, java.lang.String, int, android.service.carrier.CarrierMessagingService.ResultCallback<android.service.carrier.CarrierMessagingService.SendSmsResult>);
method public void onSendDataSms(byte[], int, java.lang.String, int, int, android.service.carrier.CarrierMessagingService.ResultCallback<android.service.carrier.CarrierMessagingService.SendSmsResult>);
method public void onSendMms(android.net.Uri, int, android.net.Uri, android.service.carrier.CarrierMessagingService.ResultCallback<android.service.carrier.CarrierMessagingService.SendMmsResult>);
@@ -36790,6 +36739,9 @@
field public static final int DOWNLOAD_STATUS_ERROR = 2; // 0x2
field public static final int DOWNLOAD_STATUS_OK = 0; // 0x0
field public static final int DOWNLOAD_STATUS_RETRY_ON_CARRIER_NETWORK = 1; // 0x1
+ field public static final int RECEIVE_OPTIONS_DEFAULT = 0; // 0x0
+ field public static final int RECEIVE_OPTIONS_DROP = 1; // 0x1
+ field public static final int RECEIVE_OPTIONS_SKIP_NOTIFY_WHEN_CREDENTIAL_ENCRYPTED_STORAGE_UNAVAILABLE = 2; // 0x2
field public static final int SEND_FLAG_REQUEST_DELIVERY_STATUS = 1; // 0x1
field public static final int SEND_STATUS_ERROR = 2; // 0x2
field public static final int SEND_STATUS_OK = 0; // 0x0
@@ -42905,6 +42857,7 @@
method public int describeContents();
method public static android.util.LocaleList forLanguageTags(java.lang.String);
method public java.util.Locale get(int);
+ method public static android.util.LocaleList getAdjustedDefault();
method public static android.util.LocaleList getDefault();
method public static android.util.LocaleList getEmptyLocaleList();
method public java.util.Locale getFirstMatch(java.lang.String[]);
@@ -53553,6 +53506,7 @@
method public static long doubleToRawLongBits(double);
method public double doubleValue();
method public float floatValue();
+ method public static int hashCode(double);
method public int intValue();
method public static boolean isInfinite(double);
method public boolean isInfinite();
@@ -53560,11 +53514,15 @@
method public boolean isNaN();
method public static double longBitsToDouble(long);
method public long longValue();
+ method public static double max(double, double);
+ method public static double min(double, double);
method public static double parseDouble(java.lang.String) throws java.lang.NumberFormatException;
+ method public static double sum(double, double);
method public static java.lang.String toHexString(double);
method public static java.lang.String toString(double);
method public static java.lang.Double valueOf(java.lang.String) throws java.lang.NumberFormatException;
method public static java.lang.Double valueOf(double);
+ field public static final int BYTES = 8; // 0x8
field public static final int MAX_EXPONENT = 1023; // 0x3ff
field public static final double MAX_VALUE = 1.7976931348623157E308;
field public static final int MIN_EXPONENT = -1022; // 0xfffffc02
@@ -53727,10 +53685,13 @@
method public static java.lang.Integer getInteger(java.lang.String);
method public static java.lang.Integer getInteger(java.lang.String, int);
method public static java.lang.Integer getInteger(java.lang.String, java.lang.Integer);
+ method public static int hashCode(int);
method public static int highestOneBit(int);
method public int intValue();
method public long longValue();
method public static int lowestOneBit(int);
+ method public static int max(int, int);
+ method public static int min(int, int);
method public static int numberOfLeadingZeros(int);
method public static int numberOfTrailingZeros(int);
method public static int parseInt(java.lang.String, int) throws java.lang.NumberFormatException;
@@ -53740,6 +53701,7 @@
method public static int rotateLeft(int, int);
method public static int rotateRight(int, int);
method public static int signum(int);
+ method public static int sum(int, int);
method public static java.lang.String toBinaryString(int);
method public static java.lang.String toHexString(int);
method public static java.lang.String toOctalString(int);
@@ -53748,6 +53710,7 @@
method public static java.lang.Integer valueOf(java.lang.String, int) throws java.lang.NumberFormatException;
method public static java.lang.Integer valueOf(java.lang.String) throws java.lang.NumberFormatException;
method public static java.lang.Integer valueOf(int);
+ field public static final int BYTES = 4; // 0x4
field public static final int MAX_VALUE = 2147483647; // 0x7fffffff
field public static final int MIN_VALUE = -2147483648; // 0x80000000
field public static final int SIZE = 32; // 0x20
@@ -53789,10 +53752,13 @@
method public static java.lang.Long getLong(java.lang.String);
method public static java.lang.Long getLong(java.lang.String, long);
method public static java.lang.Long getLong(java.lang.String, java.lang.Long);
+ method public static int hashCode(long);
method public static long highestOneBit(long);
method public int intValue();
method public long longValue();
method public static long lowestOneBit(long);
+ method public static long max(long, long);
+ method public static long min(long, long);
method public static int numberOfLeadingZeros(long);
method public static int numberOfTrailingZeros(long);
method public static long parseLong(java.lang.String, int) throws java.lang.NumberFormatException;
@@ -53802,6 +53768,7 @@
method public static long rotateLeft(long, int);
method public static long rotateRight(long, int);
method public static int signum(long);
+ method public static long sum(long, long);
method public static java.lang.String toBinaryString(long);
method public static java.lang.String toHexString(long);
method public static java.lang.String toOctalString(long);
@@ -61156,6 +61123,54 @@
method public abstract void update(java.util.Observable, java.lang.Object);
}
+ public final class Optional {
+ method public static java.util.Optional<T> empty();
+ method public java.util.Optional<T> filter(java.util.function.Predicate<? super T>);
+ method public java.util.Optional<U> flatMap(java.util.function.Function<? super T, java.util.Optional<U>>);
+ method public T get();
+ method public void ifPresent(java.util.function.Consumer<? super T>);
+ method public boolean isPresent();
+ method public java.util.Optional<U> map(java.util.function.Function<? super T, ? extends U>);
+ method public static java.util.Optional<T> of(T);
+ method public static java.util.Optional<T> ofNullable(T);
+ method public T orElse(T);
+ method public T orElseGet(java.util.function.Supplier<? extends T>);
+ method public T orElseThrow(java.util.function.Supplier<? extends X>) throws java.lang.Throwable;
+ }
+
+ public final class OptionalDouble {
+ method public static java.util.OptionalDouble empty();
+ method public double getAsDouble();
+ method public void ifPresent(java.util.function.DoubleConsumer);
+ method public boolean isPresent();
+ method public static java.util.OptionalDouble of(double);
+ method public double orElse(double);
+ method public double orElseGet(java.util.function.DoubleSupplier);
+ method public double orElseThrow(java.util.function.Supplier<X>) throws java.lang.Throwable;
+ }
+
+ public final class OptionalInt {
+ method public static java.util.OptionalInt empty();
+ method public int getAsInt();
+ method public void ifPresent(java.util.function.IntConsumer);
+ method public boolean isPresent();
+ method public static java.util.OptionalInt of(int);
+ method public int orElse(int);
+ method public int orElseGet(java.util.function.IntSupplier);
+ method public int orElseThrow(java.util.function.Supplier<X>) throws java.lang.Throwable;
+ }
+
+ public final class OptionalLong {
+ method public static java.util.OptionalLong empty();
+ method public long getAsLong();
+ method public void ifPresent(java.util.function.LongConsumer);
+ method public boolean isPresent();
+ method public static java.util.OptionalLong of(long);
+ method public long orElse(long);
+ method public long orElseGet(java.util.function.LongSupplier);
+ method public long orElseThrow(java.util.function.Supplier<X>) throws java.lang.Throwable;
+ }
+
public class PriorityQueue extends java.util.AbstractQueue implements java.io.Serializable {
ctor public PriorityQueue();
ctor public PriorityQueue(int);
diff --git a/api/test-current.txt b/api/test-current.txt
index 0bf42c3..3eae99d 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -2668,6 +2668,8 @@
field public static final int GLOBAL_ACTION_TOGGLE_SPLIT_SCREEN = 7; // 0x7
field public static final java.lang.String SERVICE_INTERFACE = "android.accessibilityservice.AccessibilityService";
field public static final java.lang.String SERVICE_META_DATA = "android.accessibilityservice";
+ field public static final int SHOW_MODE_AUTO = 0; // 0x0
+ field public static final int SHOW_MODE_HIDDEN = 1; // 0x1
}
public static abstract class AccessibilityService.GestureResultCallback {
@@ -5713,6 +5715,7 @@
public class WallpaperManager {
method public void clear() throws java.io.IOException;
+ method public void clear(int) throws java.io.IOException;
method public void clearWallpaperOffsets(android.os.IBinder);
method public void forgetLoadedWallpaper();
method public android.graphics.drawable.Drawable getBuiltInDrawable();
@@ -19163,168 +19166,110 @@
public final class GnssClock implements android.os.Parcelable {
method public int describeContents();
- method public double getBiasInNs();
- method public double getBiasUncertaintyInNs();
- method public double getDriftInNsPerSec();
- method public double getDriftUncertaintyInNsPerSec();
- method public long getFullBiasInNs();
+ method public double getBiasNanos();
+ method public double getBiasUncertaintyNanos();
+ method public double getDriftNanosPerSecond();
+ method public double getDriftUncertaintyNanosPerSecond();
+ method public long getFullBiasNanos();
method public int getHardwareClockDiscontinuityCount();
- method public short getLeapSecond();
- method public long getTimeInNs();
- method public double getTimeUncertaintyInNs();
- method public boolean hasBiasInNs();
- method public boolean hasBiasUncertaintyInNs();
- method public boolean hasDriftInNsPerSec();
- method public boolean hasDriftUncertaintyInNsPerSec();
- method public boolean hasFullBiasInNs();
+ method public int getLeapSecond();
+ method public long getTimeNanos();
+ method public double getTimeUncertaintyNanos();
+ method public boolean hasBiasNanos();
+ method public boolean hasBiasUncertaintyNanos();
+ method public boolean hasDriftNanosPerSecond();
+ method public boolean hasDriftUncertaintyNanosPerSecond();
+ method public boolean hasFullBiasNanos();
method public boolean hasLeapSecond();
- method public boolean hasTimeUncertaintyInNs();
+ method public boolean hasTimeUncertaintyNanos();
method public void reset();
- method public void resetBiasInNs();
- method public void resetBiasUncertaintyInNs();
- method public void resetDriftInNsPerSec();
- method public void resetDriftUncertaintyInNsPerSec();
- method public void resetFullBiasInNs();
+ method public void resetBiasNanos();
+ method public void resetBiasUncertaintyNanos();
+ method public void resetDriftNanosPerSecond();
+ method public void resetDriftUncertaintyNanosPerSecond();
+ method public void resetFullBiasNanos();
method public void resetLeapSecond();
- method public void resetTimeUncertaintyInNs();
+ method public void resetTimeUncertaintyNanos();
method public void set(android.location.GnssClock);
- method public void setBiasInNs(double);
- method public void setBiasUncertaintyInNs(double);
- method public void setDriftInNsPerSec(double);
- method public void setDriftUncertaintyInNsPerSec(double);
- method public void setFullBiasInNs(long);
+ method public void setBiasNanos(double);
+ method public void setBiasUncertaintyNanos(double);
+ method public void setDriftNanosPerSecond(double);
+ method public void setDriftUncertaintyNanosPerSecond(double);
+ method public void setFullBiasNanos(long);
method public void setHardwareClockDiscontinuityCount(int);
- method public void setLeapSecond(short);
- method public void setTimeInNs(long);
- method public void setTimeUncertaintyInNs(double);
+ method public void setLeapSecond(int);
+ method public void setTimeNanos(long);
+ method public void setTimeUncertaintyNanos(double);
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.location.GnssClock> CREATOR;
}
public final class GnssMeasurement implements android.os.Parcelable {
method public int describeContents();
- method public double getAccumulatedDeltaRangeInMeters();
- method public short getAccumulatedDeltaRangeState();
- method public double getAccumulatedDeltaRangeUncertaintyInMeters();
- method public double getAzimuthInDeg();
- method public double getAzimuthUncertaintyInDeg();
- method public int getBitNumber();
+ method public double getAccumulatedDeltaRangeMeters();
+ method public int getAccumulatedDeltaRangeState();
+ method public double getAccumulatedDeltaRangeUncertaintyMeters();
method public long getCarrierCycles();
- method public float getCarrierFrequencyInHz();
+ method public float getCarrierFrequencyHz();
method public double getCarrierPhase();
method public double getCarrierPhaseUncertainty();
- method public double getCn0InDbHz();
- method public double getCodePhaseInChips();
- method public double getCodePhaseUncertaintyInChips();
- method public byte getConstellationType();
- method public double getDopplerShiftInHz();
- method public double getDopplerShiftUncertaintyInHz();
- method public double getElevationInDeg();
- method public double getElevationUncertaintyInDeg();
- method public byte getLossOfLock();
- method public byte getMultipathIndicator();
- method public double getPseudorangeInMeters();
- method public double getPseudorangeRateInMetersPerSec();
- method public double getPseudorangeRateUncertaintyInMetersPerSec();
- method public double getPseudorangeUncertaintyInMeters();
- method public long getReceivedSvTimeInNs();
- method public long getReceivedSvTimeUncertaintyInNs();
+ method public double getCn0DbHz();
+ method public int getConstellationType();
+ method public int getMultipathIndicator();
+ method public double getPseudorangeRateMetersPerSecond();
+ method public double getPseudorangeRateUncertaintyMetersPerSecond();
+ method public long getReceivedSvTimeNanos();
+ method public long getReceivedSvTimeUncertaintyNanos();
method public double getSnrInDb();
- method public short getState();
- method public short getSvid();
- method public short getTimeFromLastBitInMs();
- method public double getTimeOffsetInNs();
- method public boolean hasAzimuthInDeg();
- method public boolean hasAzimuthUncertaintyInDeg();
- method public boolean hasBitNumber();
+ method public int getState();
+ method public int getSvid();
+ method public double getTimeOffsetNanos();
method public boolean hasCarrierCycles();
- method public boolean hasCarrierFrequencyInHz();
+ method public boolean hasCarrierFrequencyHz();
method public boolean hasCarrierPhase();
method public boolean hasCarrierPhaseUncertainty();
- method public boolean hasCodePhaseInChips();
- method public boolean hasCodePhaseUncertaintyInChips();
- method public boolean hasDopplerShiftInHz();
- method public boolean hasDopplerShiftUncertaintyInHz();
- method public boolean hasElevationInDeg();
- method public boolean hasElevationUncertaintyInDeg();
- method public boolean hasPseudorangeInMeters();
- method public boolean hasPseudorangeUncertaintyInMeters();
method public boolean hasSnrInDb();
- method public boolean hasTimeFromLastBitInMs();
method public boolean isPseudorangeRateCorrected();
- method public boolean isUsedInFix();
method public void reset();
- method public void resetAzimuthInDeg();
- method public void resetAzimuthUncertaintyInDeg();
- method public void resetBitNumber();
method public void resetCarrierCycles();
- method public void resetCarrierFrequencyInHz();
+ method public void resetCarrierFrequencyHz();
method public void resetCarrierPhase();
method public void resetCarrierPhaseUncertainty();
- method public void resetCodePhaseInChips();
- method public void resetCodePhaseUncertaintyInChips();
- method public void resetDopplerShiftInHz();
- method public void resetDopplerShiftUncertaintyInHz();
- method public void resetElevationInDeg();
- method public void resetElevationUncertaintyInDeg();
- method public void resetPseudorangeInMeters();
- method public void resetPseudorangeUncertaintyInMeters();
method public void resetSnrInDb();
- method public void resetTimeFromLastBitInMs();
method public void set(android.location.GnssMeasurement);
- method public void setAccumulatedDeltaRangeInMeters(double);
- method public void setAccumulatedDeltaRangeState(short);
- method public void setAccumulatedDeltaRangeUncertaintyInMeters(double);
- method public void setAzimuthInDeg(double);
- method public void setAzimuthUncertaintyInDeg(double);
- method public void setBitNumber(int);
+ method public void setAccumulatedDeltaRangeMeters(double);
+ method public void setAccumulatedDeltaRangeState(int);
+ method public void setAccumulatedDeltaRangeUncertaintyMeters(double);
method public void setCarrierCycles(long);
- method public void setCarrierFrequencyInHz(float);
+ method public void setCarrierFrequencyHz(float);
method public void setCarrierPhase(double);
method public void setCarrierPhaseUncertainty(double);
- method public void setCn0InDbHz(double);
- method public void setCodePhaseInChips(double);
- method public void setCodePhaseUncertaintyInChips(double);
- method public void setConstellationType(byte);
- method public void setDopplerShiftInHz(double);
- method public void setDopplerShiftUncertaintyInHz(double);
- method public void setElevationInDeg(double);
- method public void setElevationUncertaintyInDeg(double);
- method public void setLossOfLock(byte);
- method public void setMultipathIndicator(byte);
- method public void setPseudorangeInMeters(double);
- method public void setPseudorangeRateInMetersPerSec(double);
- method public void setPseudorangeRateUncertaintyInMetersPerSec(double);
- method public void setPseudorangeUncertaintyInMeters(double);
- method public void setReceivedSvTimeInNs(long);
- method public void setReceivedSvTimeUncertaintyInNs(long);
+ method public void setCn0DbHz(double);
+ method public void setConstellationType(int);
+ method public void setMultipathIndicator(int);
+ method public void setPseudorangeRateMetersPerSecond(double);
+ method public void setPseudorangeRateUncertaintyMetersPerSecond(double);
+ method public void setReceivedSvTimeNanos(long);
+ method public void setReceivedSvTimeUncertaintyNanos(long);
method public void setSnrInDb(double);
- method public void setState(short);
- method public void setSvid(short);
- method public void setTimeFromLastBitInMs(short);
- method public void setTimeOffsetInNs(double);
- method public void setUsedInFix(boolean);
+ method public void setState(int);
+ method public void setSvid(int);
+ method public void setTimeOffsetNanos(double);
method public void writeToParcel(android.os.Parcel, int);
- field public static final short ADR_STATE_CYCLE_SLIP = 4; // 0x4
- field public static final short ADR_STATE_RESET = 2; // 0x2
- field public static final short ADR_STATE_UNKNOWN = 0; // 0x0
- field public static final short ADR_STATE_VALID = 1; // 0x1
+ field public static final int ADR_STATE_CYCLE_SLIP = 4; // 0x4
+ field public static final int ADR_STATE_RESET = 2; // 0x2
+ field public static final int ADR_STATE_UNKNOWN = 0; // 0x0
+ field public static final int ADR_STATE_VALID = 1; // 0x1
field public static final android.os.Parcelable.Creator<android.location.GnssMeasurement> CREATOR;
- field public static final byte LOSS_OF_LOCK_CYCLE_SLIP = 2; // 0x2
- field public static final byte LOSS_OF_LOCK_OK = 1; // 0x1
- field public static final byte LOSS_OF_LOCK_UNKNOWN = 0; // 0x0
- field public static final byte MULTIPATH_INDICATOR_DETECTED = 1; // 0x1
- field public static final byte MULTIPATH_INDICATOR_NOT_USED = 2; // 0x2
- field public static final byte MULTIPATH_INDICATOR_UNKNOWN = 0; // 0x0
- field public static final short STATE_BIT_SYNC = 2; // 0x2
- field public static final short STATE_CODE_LOCK = 1; // 0x1
- field public static final short STATE_MSEC_AMBIGUOUS = 16; // 0x10
- field public static final short STATE_SUBFRAME_SYNC = 4; // 0x4
- field public static final short STATE_TOW_DECODED = 8; // 0x8
- field public static final short STATE_UNKNOWN = 0; // 0x0
- }
-
- public static abstract class GnssMeasurement.LossOfLockStatus implements java.lang.annotation.Annotation {
+ field public static final int MULTIPATH_INDICATOR_DETECTED = 1; // 0x1
+ field public static final int MULTIPATH_INDICATOR_NOT_USED = 2; // 0x2
+ field public static final int MULTIPATH_INDICATOR_UNKNOWN = 0; // 0x0
+ field public static final int STATE_BIT_SYNC = 2; // 0x2
+ field public static final int STATE_CODE_LOCK = 1; // 0x1
+ field public static final int STATE_MSEC_AMBIGUOUS = 16; // 0x10
+ field public static final int STATE_SUBFRAME_SYNC = 4; // 0x4
+ field public static final int STATE_TOW_DECODED = 8; // 0x8
+ field public static final int STATE_UNKNOWN = 0; // 0x0
}
public static abstract class GnssMeasurement.MultipathIndicator implements java.lang.annotation.Annotation {
@@ -19337,7 +19282,7 @@
method public java.util.Collection<android.location.GnssMeasurement> getMeasurements();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.location.GnssMeasurementsEvent> CREATOR;
- field public static final int STATUS_GPS_LOCATION_DISABLED = 2; // 0x2
+ field public static final int STATUS_GNSS_LOCATION_DISABLED = 2; // 0x2
field public static final int STATUS_NOT_SUPPORTED = 0; // 0x0
field public static final int STATUS_READY = 1; // 0x1
}
@@ -19354,34 +19299,34 @@
public final class GnssNavigationMessage implements android.os.Parcelable {
method public int describeContents();
method public byte[] getData();
- method public short getMessageId();
- method public short getStatus();
- method public short getSubmessageId();
- method public short getSvid();
- method public short getType();
+ method public int getMessageId();
+ method public int getStatus();
+ method public int getSubmessageId();
+ method public int getSvid();
+ method public int getType();
method public void reset();
method public void set(android.location.GnssNavigationMessage);
method public void setData(byte[]);
- method public void setMessageId(short);
- method public void setStatus(short);
- method public void setSubmessageId(short);
- method public void setSvid(short);
- method public void setType(short);
+ method public void setMessageId(int);
+ method public void setStatus(int);
+ method public void setSubmessageId(int);
+ method public void setSvid(int);
+ method public void setType(int);
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.location.GnssNavigationMessage> CREATOR;
- field public static final short MESSAGE_TYPE_BDS_D1 = 1281; // 0x501
- field public static final short MESSAGE_TYPE_BDS_D2 = 1282; // 0x502
- field public static final short MESSAGE_TYPE_GAL_F = 1538; // 0x602
- field public static final short MESSAGE_TYPE_GAL_I = 1537; // 0x601
- field public static final short MESSAGE_TYPE_GLO_L1CA = 769; // 0x301
- field public static final short MESSAGE_TYPE_GPS_CNAV2 = 260; // 0x104
- field public static final short MESSAGE_TYPE_GPS_L1CA = 257; // 0x101
- field public static final short MESSAGE_TYPE_GPS_L2CNAV = 258; // 0x102
- field public static final short MESSAGE_TYPE_GPS_L5CNAV = 259; // 0x103
- field public static final short MESSAGE_TYPE_UNKNOWN = 0; // 0x0
- field public static final short STATUS_PARITY_PASSED = 1; // 0x1
- field public static final short STATUS_PARITY_REBUILT = 2; // 0x2
- field public static final short STATUS_UNKNOWN = 0; // 0x0
+ field public static final int STATUS_PARITY_PASSED = 1; // 0x1
+ field public static final int STATUS_PARITY_REBUILT = 2; // 0x2
+ field public static final int STATUS_UNKNOWN = 0; // 0x0
+ field public static final int TYPE_BDS_D1 = 1281; // 0x501
+ field public static final int TYPE_BDS_D2 = 1282; // 0x502
+ field public static final int TYPE_GAL_F = 1538; // 0x602
+ field public static final int TYPE_GAL_I = 1537; // 0x601
+ field public static final int TYPE_GLO_L1CA = 769; // 0x301
+ field public static final int TYPE_GPS_CNAV2 = 260; // 0x104
+ field public static final int TYPE_GPS_L1CA = 257; // 0x101
+ field public static final int TYPE_GPS_L2CNAV = 258; // 0x102
+ field public static final int TYPE_GPS_L5CNAV = 259; // 0x103
+ field public static final int TYPE_UNKNOWN = 0; // 0x0
}
public static abstract class GnssNavigationMessage.GnssNavigationMessageType implements java.lang.annotation.Annotation {
@@ -19393,7 +19338,7 @@
method public android.location.GnssNavigationMessage getNavigationMessage();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.location.GnssNavigationMessageEvent> CREATOR;
- field public static final int STATUS_GPS_LOCATION_DISABLED = 2; // 0x2
+ field public static final int STATUS_GNSS_LOCATION_DISABLED = 2; // 0x2
field public static final int STATUS_NOT_SUPPORTED = 0; // 0x0
field public static final int STATUS_READY = 1; // 0x1
}
@@ -19412,22 +19357,22 @@
}
public final class GnssStatus {
- method public float getAzimuth(int);
- method public byte getConstellationType(int);
- method public float getElevation(int);
+ method public float getAzimuthDegrees(int);
+ method public float getCn0DbHz(int);
+ method public int getConstellationType(int);
+ method public float getElevationDegrees(int);
method public int getNumSatellites();
- method public float getSnr(int);
method public int getSvid(int);
method public boolean hasAlmanac(int);
method public boolean hasEphemeris(int);
method public boolean usedInFix(int);
- field public static final byte CONSTELLATION_BEIDOU = 5; // 0x5
- field public static final byte CONSTELLATION_GALILEO = 6; // 0x6
- field public static final byte CONSTELLATION_GLONASS = 3; // 0x3
- field public static final byte CONSTELLATION_GPS = 1; // 0x1
- field public static final byte CONSTELLATION_QZSS = 4; // 0x4
- field public static final byte CONSTELLATION_SBAS = 2; // 0x2
- field public static final byte CONSTELLATION_UNKNOWN = 0; // 0x0
+ field public static final int CONSTELLATION_BEIDOU = 5; // 0x5
+ field public static final int CONSTELLATION_GALILEO = 6; // 0x6
+ field public static final int CONSTELLATION_GLONASS = 3; // 0x3
+ field public static final int CONSTELLATION_GPS = 1; // 0x1
+ field public static final int CONSTELLATION_QZSS = 4; // 0x4
+ field public static final int CONSTELLATION_SBAS = 2; // 0x2
+ field public static final int CONSTELLATION_UNKNOWN = 0; // 0x0
}
public static abstract class GnssStatus.ConstellationType implements java.lang.annotation.Annotation {
@@ -19543,8 +19488,8 @@
method public java.util.List<java.lang.String> getProviders(boolean);
method public java.util.List<java.lang.String> getProviders(android.location.Criteria, boolean);
method public boolean isProviderEnabled(java.lang.String);
- method public boolean registerGnssMeasurementCallback(android.location.GnssMeasurementsEvent.Callback);
- method public boolean registerGnssMeasurementCallback(android.location.GnssMeasurementsEvent.Callback, android.os.Handler);
+ method public boolean registerGnssMeasurementsCallback(android.location.GnssMeasurementsEvent.Callback);
+ method public boolean registerGnssMeasurementsCallback(android.location.GnssMeasurementsEvent.Callback, android.os.Handler);
method public boolean registerGnssNavigationMessageCallback(android.location.GnssNavigationMessageEvent.Callback);
method public boolean registerGnssNavigationMessageCallback(android.location.GnssNavigationMessageEvent.Callback, android.os.Handler);
method public boolean registerGnssStatusCallback(android.location.GnssStatusCallback);
@@ -19569,7 +19514,7 @@
method public void setTestProviderEnabled(java.lang.String, boolean);
method public void setTestProviderLocation(java.lang.String, android.location.Location);
method public void setTestProviderStatus(java.lang.String, int, android.os.Bundle, long);
- method public void unregisterGnssMeasurementCallback(android.location.GnssMeasurementsEvent.Callback);
+ method public void unregisterGnssMeasurementsCallback(android.location.GnssMeasurementsEvent.Callback);
method public void unregisterGnssNavigationMessageCallback(android.location.GnssNavigationMessageEvent.Callback);
method public void unregisterGnssStatusCallback(android.location.GnssStatusCallback);
field public static final java.lang.String GPS_PROVIDER = "gps";
@@ -21001,6 +20946,7 @@
field public static final java.lang.String KEY_SLICE_HEIGHT = "slice-height";
field public static final java.lang.String KEY_STRIDE = "stride";
field public static final java.lang.String KEY_TEMPORAL_LAYERING = "ts-schema";
+ field public static final java.lang.String KEY_TRACK_ID = "track-id";
field public static final java.lang.String KEY_WIDTH = "width";
field public static final java.lang.String MIMETYPE_AUDIO_AAC = "audio/mp4a-latm";
field public static final java.lang.String MIMETYPE_AUDIO_AC3 = "audio/ac3";
@@ -29113,6 +29059,8 @@
ctor public Process();
method public static final long getElapsedCpuTime();
method public static final int getGidForName(java.lang.String);
+ method public static final long getStartElapsedRealtime();
+ method public static final long getStartUptimeMillis();
method public static final int getThreadPriority(int) throws java.lang.IllegalArgumentException;
method public static final int getUidForName(java.lang.String);
method public static final boolean is64Bit();
@@ -34306,7 +34254,8 @@
ctor public CarrierMessagingService();
method public android.os.IBinder onBind(android.content.Intent);
method public void onDownloadMms(android.net.Uri, int, android.net.Uri, android.service.carrier.CarrierMessagingService.ResultCallback<java.lang.Integer>);
- method public void onFilterSms(android.service.carrier.MessagePdu, java.lang.String, int, int, android.service.carrier.CarrierMessagingService.ResultCallback<java.lang.Boolean>);
+ method public deprecated void onFilterSms(android.service.carrier.MessagePdu, java.lang.String, int, int, android.service.carrier.CarrierMessagingService.ResultCallback<java.lang.Boolean>);
+ method public void onReceiveTextSms(android.service.carrier.MessagePdu, java.lang.String, int, int, android.service.carrier.CarrierMessagingService.ResultCallback<java.lang.Integer>);
method public deprecated void onSendDataSms(byte[], int, java.lang.String, int, android.service.carrier.CarrierMessagingService.ResultCallback<android.service.carrier.CarrierMessagingService.SendSmsResult>);
method public void onSendDataSms(byte[], int, java.lang.String, int, int, android.service.carrier.CarrierMessagingService.ResultCallback<android.service.carrier.CarrierMessagingService.SendSmsResult>);
method public void onSendMms(android.net.Uri, int, android.net.Uri, android.service.carrier.CarrierMessagingService.ResultCallback<android.service.carrier.CarrierMessagingService.SendMmsResult>);
@@ -34317,6 +34266,9 @@
field public static final int DOWNLOAD_STATUS_ERROR = 2; // 0x2
field public static final int DOWNLOAD_STATUS_OK = 0; // 0x0
field public static final int DOWNLOAD_STATUS_RETRY_ON_CARRIER_NETWORK = 1; // 0x1
+ field public static final int RECEIVE_OPTIONS_DEFAULT = 0; // 0x0
+ field public static final int RECEIVE_OPTIONS_DROP = 1; // 0x1
+ field public static final int RECEIVE_OPTIONS_SKIP_NOTIFY_WHEN_CREDENTIAL_ENCRYPTED_STORAGE_UNAVAILABLE = 2; // 0x2
field public static final int SEND_FLAG_REQUEST_DELIVERY_STATUS = 1; // 0x1
field public static final int SEND_STATUS_ERROR = 2; // 0x2
field public static final int SEND_STATUS_OK = 0; // 0x0
@@ -40157,6 +40109,7 @@
method public int describeContents();
method public static android.util.LocaleList forLanguageTags(java.lang.String);
method public java.util.Locale get(int);
+ method public static android.util.LocaleList getAdjustedDefault();
method public static android.util.LocaleList getDefault();
method public static android.util.LocaleList getEmptyLocaleList();
method public java.util.Locale getFirstMatch(java.lang.String[]);
@@ -50468,6 +50421,7 @@
method public static long doubleToRawLongBits(double);
method public double doubleValue();
method public float floatValue();
+ method public static int hashCode(double);
method public int intValue();
method public static boolean isInfinite(double);
method public boolean isInfinite();
@@ -50475,11 +50429,15 @@
method public boolean isNaN();
method public static double longBitsToDouble(long);
method public long longValue();
+ method public static double max(double, double);
+ method public static double min(double, double);
method public static double parseDouble(java.lang.String) throws java.lang.NumberFormatException;
+ method public static double sum(double, double);
method public static java.lang.String toHexString(double);
method public static java.lang.String toString(double);
method public static java.lang.Double valueOf(java.lang.String) throws java.lang.NumberFormatException;
method public static java.lang.Double valueOf(double);
+ field public static final int BYTES = 8; // 0x8
field public static final int MAX_EXPONENT = 1023; // 0x3ff
field public static final double MAX_VALUE = 1.7976931348623157E308;
field public static final int MIN_EXPONENT = -1022; // 0xfffffc02
@@ -50642,10 +50600,13 @@
method public static java.lang.Integer getInteger(java.lang.String);
method public static java.lang.Integer getInteger(java.lang.String, int);
method public static java.lang.Integer getInteger(java.lang.String, java.lang.Integer);
+ method public static int hashCode(int);
method public static int highestOneBit(int);
method public int intValue();
method public long longValue();
method public static int lowestOneBit(int);
+ method public static int max(int, int);
+ method public static int min(int, int);
method public static int numberOfLeadingZeros(int);
method public static int numberOfTrailingZeros(int);
method public static int parseInt(java.lang.String, int) throws java.lang.NumberFormatException;
@@ -50655,6 +50616,7 @@
method public static int rotateLeft(int, int);
method public static int rotateRight(int, int);
method public static int signum(int);
+ method public static int sum(int, int);
method public static java.lang.String toBinaryString(int);
method public static java.lang.String toHexString(int);
method public static java.lang.String toOctalString(int);
@@ -50663,6 +50625,7 @@
method public static java.lang.Integer valueOf(java.lang.String, int) throws java.lang.NumberFormatException;
method public static java.lang.Integer valueOf(java.lang.String) throws java.lang.NumberFormatException;
method public static java.lang.Integer valueOf(int);
+ field public static final int BYTES = 4; // 0x4
field public static final int MAX_VALUE = 2147483647; // 0x7fffffff
field public static final int MIN_VALUE = -2147483648; // 0x80000000
field public static final int SIZE = 32; // 0x20
@@ -50704,10 +50667,13 @@
method public static java.lang.Long getLong(java.lang.String);
method public static java.lang.Long getLong(java.lang.String, long);
method public static java.lang.Long getLong(java.lang.String, java.lang.Long);
+ method public static int hashCode(long);
method public static long highestOneBit(long);
method public int intValue();
method public long longValue();
method public static long lowestOneBit(long);
+ method public static long max(long, long);
+ method public static long min(long, long);
method public static int numberOfLeadingZeros(long);
method public static int numberOfTrailingZeros(long);
method public static long parseLong(java.lang.String, int) throws java.lang.NumberFormatException;
@@ -50717,6 +50683,7 @@
method public static long rotateLeft(long, int);
method public static long rotateRight(long, int);
method public static int signum(long);
+ method public static long sum(long, long);
method public static java.lang.String toBinaryString(long);
method public static java.lang.String toHexString(long);
method public static java.lang.String toOctalString(long);
@@ -58071,6 +58038,54 @@
method public abstract void update(java.util.Observable, java.lang.Object);
}
+ public final class Optional {
+ method public static java.util.Optional<T> empty();
+ method public java.util.Optional<T> filter(java.util.function.Predicate<? super T>);
+ method public java.util.Optional<U> flatMap(java.util.function.Function<? super T, java.util.Optional<U>>);
+ method public T get();
+ method public void ifPresent(java.util.function.Consumer<? super T>);
+ method public boolean isPresent();
+ method public java.util.Optional<U> map(java.util.function.Function<? super T, ? extends U>);
+ method public static java.util.Optional<T> of(T);
+ method public static java.util.Optional<T> ofNullable(T);
+ method public T orElse(T);
+ method public T orElseGet(java.util.function.Supplier<? extends T>);
+ method public T orElseThrow(java.util.function.Supplier<? extends X>) throws java.lang.Throwable;
+ }
+
+ public final class OptionalDouble {
+ method public static java.util.OptionalDouble empty();
+ method public double getAsDouble();
+ method public void ifPresent(java.util.function.DoubleConsumer);
+ method public boolean isPresent();
+ method public static java.util.OptionalDouble of(double);
+ method public double orElse(double);
+ method public double orElseGet(java.util.function.DoubleSupplier);
+ method public double orElseThrow(java.util.function.Supplier<X>) throws java.lang.Throwable;
+ }
+
+ public final class OptionalInt {
+ method public static java.util.OptionalInt empty();
+ method public int getAsInt();
+ method public void ifPresent(java.util.function.IntConsumer);
+ method public boolean isPresent();
+ method public static java.util.OptionalInt of(int);
+ method public int orElse(int);
+ method public int orElseGet(java.util.function.IntSupplier);
+ method public int orElseThrow(java.util.function.Supplier<X>) throws java.lang.Throwable;
+ }
+
+ public final class OptionalLong {
+ method public static java.util.OptionalLong empty();
+ method public long getAsLong();
+ method public void ifPresent(java.util.function.LongConsumer);
+ method public boolean isPresent();
+ method public static java.util.OptionalLong of(long);
+ method public long orElse(long);
+ method public long orElseGet(java.util.function.LongSupplier);
+ method public long orElseThrow(java.util.function.Supplier<X>) throws java.lang.Throwable;
+ }
+
public class PriorityQueue extends java.util.AbstractQueue implements java.io.Serializable {
ctor public PriorityQueue();
ctor public PriorityQueue(int);
diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java
index df0e5fc..fea6f0e 100644
--- a/cmds/am/src/com/android/commands/am/Am.java
+++ b/cmds/am/src/com/android/commands/am/Am.java
@@ -606,7 +606,7 @@
new File(mProfileFile),
ParcelFileDescriptor.MODE_CREATE |
ParcelFileDescriptor.MODE_TRUNCATE |
- ParcelFileDescriptor.MODE_READ_WRITE);
+ ParcelFileDescriptor.MODE_WRITE_ONLY);
} catch (FileNotFoundException e) {
System.err.println("Error: Unable to open file: " + mProfileFile);
System.err.println("Consider using a file under /data/local/tmp/");
@@ -903,7 +903,7 @@
fd = openForSystemServer(file,
ParcelFileDescriptor.MODE_CREATE |
ParcelFileDescriptor.MODE_TRUNCATE |
- ParcelFileDescriptor.MODE_READ_WRITE);
+ ParcelFileDescriptor.MODE_WRITE_ONLY);
} catch (FileNotFoundException e) {
System.err.println("Error: Unable to open file: " + filename);
System.err.println("Consider using a file under /data/local/tmp/");
@@ -992,7 +992,7 @@
new File(profileFile),
ParcelFileDescriptor.MODE_CREATE |
ParcelFileDescriptor.MODE_TRUNCATE |
- ParcelFileDescriptor.MODE_READ_WRITE);
+ ParcelFileDescriptor.MODE_WRITE_ONLY);
} catch (FileNotFoundException e) {
System.err.println("Error: Unable to open file: " + profileFile);
System.err.println("Consider using a file under /data/local/tmp/");
@@ -1052,7 +1052,7 @@
fd = openForSystemServer(file,
ParcelFileDescriptor.MODE_CREATE |
ParcelFileDescriptor.MODE_TRUNCATE |
- ParcelFileDescriptor.MODE_READ_WRITE);
+ ParcelFileDescriptor.MODE_WRITE_ONLY);
} catch (FileNotFoundException e) {
System.err.println("Error: Unable to open file: " + heapFile);
System.err.println("Consider using a file under /data/local/tmp/");
diff --git a/core/java/android/accessibilityservice/AccessibilityService.java b/core/java/android/accessibilityservice/AccessibilityService.java
index fb5f5b9..ac3b8e3 100644
--- a/core/java/android/accessibilityservice/AccessibilityService.java
+++ b/core/java/android/accessibilityservice/AccessibilityService.java
@@ -383,13 +383,7 @@
@Retention(RetentionPolicy.SOURCE)
@IntDef({SHOW_MODE_AUTO, SHOW_MODE_HIDDEN})
public @interface SoftKeyboardShowMode {};
- /**
- * @hide
- */
public static final int SHOW_MODE_AUTO = 0;
- /**
- * @hide
- */
public static final int SHOW_MODE_HIDDEN = 1;
private int mConnectionId;
@@ -1137,7 +1131,7 @@
}
/**
- * Removes all instances of the specified change listener from teh list of magnification
+ * Removes all instances of the specified change listener from the list of magnification
* change listeners.
*
* @param listener the listener to remove, must be non-null
@@ -1216,14 +1210,11 @@
/**
* Returns the show mode of the soft keyboard. The default show mode is
- * {@code Settings.Secure.SHOW_MODE_AUTO}, where the soft keyboard is shown when a text
- * input field is focused. An AccessibilityService can also request the show mode
- * {@code Settings.Secure.SHOW_MODE_HIDDEN}, where the soft keyboard is never shown.
+ * {@code SHOW_MODE_AUTO}, where the soft keyboard is shown when a text input field is
+ * focused. An AccessibilityService can also request the show mode
+ * {@code SHOW_MODE_HIDDEN}, where the soft keyboard is never shown.
*
* @return the current soft keyboard show mode
- *
- * @see Settings#Secure#SHOW_MODE_AUTO
- * @see Settings#Secure#SHOW_MODE_HIDDEN
*/
@SoftKeyboardShowMode
public int getShowMode() {
@@ -1239,9 +1230,9 @@
/**
* Sets the soft keyboard show mode. The default show mode is
- * {@code Settings.Secure.SHOW_MODE_AUTO}, where the soft keyboard is shown when a text
- * input field is focused. An AccessibilityService can also request the show mode
- * {@code Settings.Secure.SHOW_MODE_HIDDEN}, where the soft keyboard is never shown. The
+ * {@code SHOW_MODE_AUTO}, where the soft keyboard is shown when a text input field is
+ * focused. An AccessibilityService can also request the show mode
+ * {@code SHOW_MODE_HIDDEN}, where the soft keyboard is never shown. The
* The lastto this method will be honored, regardless of any previous calls (including those
* made by other AccessibilityServices).
* <p>
@@ -1251,9 +1242,6 @@
*
* @param showMode the new show mode for the soft keyboard
* @return {@code true} on success
- *
- * @see Settings#Secure#SHOW_MODE_AUTO
- * @see Settings#Secure#SHOW_MODE_HIDDEN
*/
public boolean setShowMode(@SoftKeyboardShowMode int showMode) {
final IAccessibilityServiceConnection connection =
@@ -1263,9 +1251,13 @@
try {
return connection.setSoftKeyboardShowMode(showMode);
} catch (RemoteException re) {
- Log.w(LOG_TAG, "Falied to set soft keyboard behavior", re);
+ Log.w(LOG_TAG, "Failed to set soft keyboard behavior", re);
+ re.rethrowFromSystemServer();
}
+ } else {
+ throw new RuntimeException("AccessibilityServiceConnection is null");
}
+
return false;
}
@@ -1275,9 +1267,9 @@
public interface OnShowModeChangedListener {
/**
* Called when the soft keyboard behavior changes. The default show mode is
- * {@code Settings.Secure.SHOW_MODE_AUTO}, where the soft keyboard is shown when a text
- * input field is focused. An AccessibilityService can also request the show mode
- * {@code Settings.Secure.SHOW_MODE_HIDDEN}, where the soft keyboard is never shown.
+ * {@code SHOW_MODE_AUTO}, where the soft keyboard is shown when a text input field is
+ * focused. An AccessibilityService can also request the show mode
+ * {@code SHOW_MODE_HIDDEN}, where the soft keyboard is never shown.
*
* @param controller the soft keyboard controller
* @param showMode the current soft keyboard show mode
diff --git a/core/java/android/animation/AnimatorInflater.java b/core/java/android/animation/AnimatorInflater.java
index 20d71a6..8d03b55 100644
--- a/core/java/android/animation/AnimatorInflater.java
+++ b/core/java/android/animation/AnimatorInflater.java
@@ -108,7 +108,7 @@
float pathErrorScale) throws NotFoundException {
final ConfigurationBoundResourceCache<Animator> animatorCache = resources
.getAnimatorCache();
- Animator animator = animatorCache.getInstance(id, theme);
+ Animator animator = animatorCache.getInstance(id, resources, theme);
if (animator != null) {
if (DBG_ANIMATOR_INFLATER) {
Log.d(TAG, "loaded animator from cache, " + resources.getResourceName(id));
@@ -157,7 +157,7 @@
final ConfigurationBoundResourceCache<StateListAnimator> cache = resources
.getStateListAnimatorCache();
final Theme theme = context.getTheme();
- StateListAnimator animator = cache.getInstance(id, theme);
+ StateListAnimator animator = cache.getInstance(id, resources, theme);
if (animator != null) {
return animator;
}
diff --git a/core/java/android/animation/ValueAnimator.java b/core/java/android/animation/ValueAnimator.java
index e721de9..5ab2c1d 100644
--- a/core/java/android/animation/ValueAnimator.java
+++ b/core/java/android/animation/ValueAnimator.java
@@ -1029,8 +1029,16 @@
@Override
public void resume() {
- if (mPaused) {
+ if (Looper.myLooper() == null) {
+ throw new AndroidRuntimeException("Animators may only be resumed from the same " +
+ "thread that the animator was started on");
+ }
+ if (mPaused && !mResumed) {
mResumed = true;
+ if (mPauseTime > 0) {
+ AnimationHandler handler = AnimationHandler.getInstance();
+ handler.addAnimationFrameCallback(this, 0);
+ }
}
super.resume();
}
@@ -1235,9 +1243,8 @@
}
mLastFrameTime = frameTime;
if (mPaused) {
- if (mPauseTime < 0) {
- mPauseTime = frameTime;
- }
+ mPauseTime = frameTime;
+ handler.removeCallback(this);
return;
} else if (mResumed) {
mResumed = false;
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index be89b20..b87e9fa2 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -6599,7 +6599,8 @@
if (isAppDebuggable || isDlwarningEnabled) {
String dlwarning = getDlWarning();
if (dlwarning != null) {
- String appName = getString(mApplication.getApplicationInfo().labelRes);
+ String appName = getApplicationInfo().loadLabel(getPackageManager())
+ .toString();
String warning = "Detected problems with app native libraries\n" +
"(please consult log for detail):\n" + dlwarning;
if (isAppDebuggable) {
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 4aab163..a4e5b90 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -577,6 +577,16 @@
}
/**
+ * Return whether a stackId is a stack containing floating windows. Floating windows
+ * are laid out differently as they are allowed to extend past the display bounds
+ * without overscan insets.
+ */
+ public static boolean tasksAreFloating(int stackId) {
+ return stackId == FREEFORM_WORKSPACE_STACK_ID
+ || stackId == PINNED_STACK_ID;
+ }
+
+ /**
* Returns true if animation specs should be constructed for app transition that moves
* the task to the specified stack.
*/
@@ -647,6 +657,16 @@
return stackId != PINNED_STACK_ID && stackId != FREEFORM_WORKSPACE_STACK_ID
&& stackId != DOCKED_STACK_ID;
}
+
+ /**
+ * Returns true if the input stack id should only be present on a device that supports
+ * multi-window mode.
+ * @see android.app.ActivityManager#supportsMultiWindow
+ */
+ public static boolean isMultiWindowStack(int stackId) {
+ return isStaticStack(stackId) || stackId == PINNED_STACK_ID
+ || stackId == FREEFORM_WORKSPACE_STACK_ID || stackId == DOCKED_STACK_ID;
+ }
}
/**
@@ -868,6 +888,17 @@
}
/**
+ * Returns true if the system supports at least one form of multi-window.
+ * E.g. freeform, split-screen, picture-in-picture.
+ * @hide
+ */
+ static public boolean supportsMultiWindow() {
+ return !isLowRamDeviceStatic()
+ && Resources.getSystem().getBoolean(
+ com.android.internal.R.bool.config_supportsMultiWindow);
+ }
+
+ /**
* Information you can set and retrieve about the current activity within the recent task list.
*/
public static class TaskDescription implements Parcelable {
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index b264e8e..ff7f70d 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -792,8 +792,9 @@
if (hasBounds) {
bounds = Rect.CREATOR.createFromParcel(data);
}
- moveTaskToDockedStack(taskId, createMode, toTop, animate, bounds);
+ boolean res = moveTaskToDockedStack(taskId, createMode, toTop, animate, bounds);
reply.writeNoException();
+ reply.writeInt(res ? 1 : 0);
return true;
}
@@ -822,7 +823,21 @@
reply.writeNoException();
return true;
}
-
+ case RESIZE_PINNED_STACK_TRANSACTION: {
+ data.enforceInterface(IActivityManager.descriptor);
+ final boolean hasBounds = data.readInt() != 0;
+ Rect bounds = null;
+ if (hasBounds) {
+ bounds = Rect.CREATOR.createFromParcel(data);
+ }
+ final boolean hasTempPinnedTaskBounds = data.readInt() != 0;
+ Rect tempPinnedTaskBounds = null;
+ if (hasTempPinnedTaskBounds) {
+ tempPinnedTaskBounds = Rect.CREATOR.createFromParcel(data);
+ }
+ resizePinnedStack(bounds, tempPinnedTaskBounds);
+ return true;
+ }
case RESIZE_DOCKED_STACK_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor);
final boolean hasBounds = data.readInt() != 0;
@@ -3809,7 +3824,7 @@
reply.recycle();
}
@Override
- public void moveTaskToDockedStack(int taskId, int createMode, boolean toTop, boolean animate,
+ public boolean moveTaskToDockedStack(int taskId, int createMode, boolean toTop, boolean animate,
Rect initialBounds) throws RemoteException
{
Parcel data = Parcel.obtain();
@@ -3827,8 +3842,10 @@
}
mRemote.transact(MOVE_TASK_TO_DOCKED_STACK_TRANSACTION, data, reply, 0);
reply.readException();
+ boolean res = reply.readInt() > 0;
data.recycle();
reply.recycle();
+ return res;
}
@Override
public boolean moveTopActivityToPinnedStack(int stackId, Rect r)
@@ -3911,6 +3928,31 @@
data.recycle();
reply.recycle();
}
+
+ @Override
+ public void resizePinnedStack(Rect pinnedBounds, Rect tempPinnedTaskBounds) throws RemoteException
+ {
+ Parcel data = Parcel.obtain();
+ Parcel reply = Parcel.obtain();
+ data.writeInterfaceToken(IActivityManager.descriptor);
+ if (pinnedBounds != null) {
+ data.writeInt(1);
+ pinnedBounds.writeToParcel(data, 0);
+ } else {
+ data.writeInt(0);
+ }
+ if (tempPinnedTaskBounds != null) {
+ data.writeInt(1);
+ tempPinnedTaskBounds.writeToParcel(data, 0);
+ } else {
+ data.writeInt(0);
+ }
+ mRemote.transact(RESIZE_PINNED_STACK_TRANSACTION, data, reply, 0);
+ reply.readException();
+ data.recycle();
+ reply.recycle();
+ }
+
@Override
public void positionTaskInStack(int taskId, int stackId, int position) throws RemoteException
{
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index e41b792..1bc33b8 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -1788,7 +1788,8 @@
}
/**
- * Creates the top level resources for the given package.
+ * Creates the top level resources for the given package. Will return an existing
+ * Resources if one has already been created.
*/
Resources getTopLevelResources(String resDir, String[] splitResDirs, String[] overlayDirs,
String[] libDirs, int displayId, Configuration overrideConfiguration,
@@ -1798,6 +1799,19 @@
pkgInfo.getClassLoader());
}
+ /**
+ * Creates a new top level resources for the given package. Will always create a new
+ * Resources, regardless if one has already been created.
+ */
+ Resources getNewTopLevelResources(String resDir, String[] splitResDirs, String[] overlayDirs,
+ String[] libDirs, int displayId, Configuration overrideConfiguration,
+ LoadedApk pkgInfo) {
+ mResourcesManager.removeTopLevelResources(
+ resDir, displayId, overrideConfiguration, pkgInfo.getCompatibilityInfo());
+ return getTopLevelResources(resDir, splitResDirs, overlayDirs, libDirs,
+ displayId, overrideConfiguration, pkgInfo);
+ }
+
final Handler getHandler() {
return mH;
}
@@ -3345,6 +3359,18 @@
}
r.activity.performResume();
+ // If there is a pending local relaunch that was requested when the activity was
+ // paused, it will put the activity into paused state when it finally happens.
+ // Since the activity resumed before being relaunched, we don't want that to happen,
+ // so we need to clear the request to relaunch paused.
+ for (int i = mRelaunchingActivities.size() - 1; i >= 0; i--) {
+ final ActivityClientRecord relaunching = mRelaunchingActivities.get(i);
+ if (relaunching.token == r.token
+ && relaunching.onlyLocalRequest && relaunching.startsNotResumed) {
+ relaunching.startsNotResumed = false;
+ }
+ }
+
EventLog.writeEvent(LOG_AM_ON_RESUME_CALLED, UserHandle.myUserId(),
r.activity.getComponentName().getClassName(), reason);
@@ -3576,6 +3602,7 @@
private void handlePauseActivity(IBinder token, boolean finished,
boolean userLeaving, int configChanges, boolean dontReport, int seq) {
ActivityClientRecord r = mActivities.get(token);
+ if (DEBUG_ORDER) Slog.d(TAG, "handlePauseActivity " + r + ", seq: " + seq);
if (!checkAndUpdateLifecycleSeq(seq, r, "pauseActivity")) {
return;
}
@@ -4230,6 +4257,7 @@
synchronized (mResourcesManager) {
for (int i=0; i<mRelaunchingActivities.size(); i++) {
ActivityClientRecord r = mRelaunchingActivities.get(i);
+ if (DEBUG_ORDER) Slog.d(TAG, "requestRelaunchActivity: " + this + ", trying: " + r);
if (r.token == token) {
target = r;
if (pendingResults != null) {
@@ -4260,14 +4288,19 @@
}
if (target == null) {
+ if (DEBUG_ORDER) Slog.d(TAG, "requestRelaunchActivity: target is null, fromServer:"
+ + fromServer);
target = new ActivityClientRecord();
target.token = token;
target.pendingResults = pendingResults;
target.pendingIntents = pendingNewIntents;
target.mPreserveWindow = preserveWindow;
if (!fromServer) {
- ActivityClientRecord existing = mActivities.get(token);
+ final ActivityClientRecord existing = mActivities.get(token);
+ if (DEBUG_ORDER) Slog.d(TAG, "requestRelaunchActivity: " + existing);
if (existing != null) {
+ if (DEBUG_ORDER) Slog.d(TAG, "requestRelaunchActivity: paused= "
+ + existing.paused);;
target.startsNotResumed = existing.paused;
target.overrideConfig = existing.overrideConfig;
}
@@ -4290,8 +4323,8 @@
target.pendingConfigChanges |= configChanges;
target.relaunchSeq = getLifecycleSeq();
}
- if (DEBUG_ORDER) Slog.d(TAG, "relaunchActivity " + ActivityThread.this
- + " operation received seq: " + target.relaunchSeq);
+ if (DEBUG_ORDER) Slog.d(TAG, "relaunchActivity " + ActivityThread.this + ", target "
+ + target + " operation received seq: " + target.relaunchSeq);
}
private void handleRelaunchActivity(ActivityClientRecord tmp) {
@@ -4730,29 +4763,87 @@
final void handleDispatchPackageBroadcast(int cmd, String[] packages) {
boolean hasPkgInfo = false;
- if (packages != null) {
- synchronized (mResourcesManager) {
- for (int i=packages.length-1; i>=0; i--) {
- //Slog.i(TAG, "Cleaning old package: " + packages[i]);
- if (!hasPkgInfo) {
- WeakReference<LoadedApk> ref;
- ref = mPackages.get(packages[i]);
- if (ref != null && ref.get() != null) {
+ switch (cmd) {
+ case IApplicationThread.PACKAGE_REMOVED:
+ case IApplicationThread.PACKAGE_REMOVED_DONT_KILL:
+ {
+ final boolean killApp = cmd == IApplicationThread.PACKAGE_REMOVED;
+ if (packages == null) {
+ break;
+ }
+ synchronized (mResourcesManager) {
+ for (int i = packages.length - 1; i >= 0; i--) {
+ if (!hasPkgInfo) {
+ WeakReference<LoadedApk> ref = mPackages.get(packages[i]);
+ if (ref != null && ref.get() != null) {
+ hasPkgInfo = true;
+ } else {
+ ref = mResourcePackages.get(packages[i]);
+ if (ref != null && ref.get() != null) {
+ hasPkgInfo = true;
+ }
+ }
+ }
+ if (killApp) {
+ mPackages.remove(packages[i]);
+ mResourcePackages.remove(packages[i]);
+ }
+ }
+ }
+ break;
+ }
+ case IApplicationThread.PACKAGE_REPLACED:
+ {
+ if (packages == null) {
+ break;
+ }
+ synchronized (mResourcesManager) {
+ for (int i = packages.length - 1; i >= 0; i--) {
+ WeakReference<LoadedApk> ref = mPackages.get(packages[i]);
+ LoadedApk pkgInfo = ref != null ? ref.get() : null;
+ if (pkgInfo != null) {
hasPkgInfo = true;
} else {
ref = mResourcePackages.get(packages[i]);
- if (ref != null && ref.get() != null) {
+ pkgInfo = ref != null ? ref.get() : null;
+ if (pkgInfo != null) {
hasPkgInfo = true;
}
}
+ // If the package is being replaced, yet it still has a valid
+ // LoadedApk object, the package was updated with _DONT_KILL.
+ // Adjust it's internal references to the application info and
+ // resources.
+ if (pkgInfo != null) {
+ try {
+ final String packageName = packages[i];
+ final ApplicationInfo aInfo =
+ sPackageManager.getApplicationInfo(
+ packageName,
+ 0 /*flags*/,
+ UserHandle.myUserId());
+
+ if (mActivities.size() > 0) {
+ for (ActivityClientRecord ar : mActivities.values()) {
+ if (ar.activityInfo.applicationInfo.packageName
+ .equals(packageName)) {
+ ar.activityInfo.applicationInfo = aInfo;
+ ar.packageInfo = pkgInfo;
+ }
+ }
+ }
+ final List<String> oldPaths =
+ sPackageManager.getPreviousCodePaths(packageName);
+ pkgInfo.updateApplicationInfo(aInfo, oldPaths);
+ } catch (RemoteException e) {
+ }
+ }
}
- mPackages.remove(packages[i]);
- mResourcePackages.remove(packages[i]);
}
+ break;
}
}
- ApplicationPackageManager.handlePackageBroadcast(cmd, packages,
- hasPkgInfo);
+ ApplicationPackageManager.handlePackageBroadcast(cmd, packages, hasPkgInfo);
}
final void handleLowMemory() {
@@ -4846,11 +4937,15 @@
Os.fchmod(fd, permissions);
Os.fchown(fd, appInfo.uid, appInfo.uid);
} catch (ErrnoException e) {
- Log.v(TAG, "Unable to create jit profile file " + profileFile, e);
+ Log.v(TAG, "Unable to create jit profile file "
+ + profileFile + ": " + e.getMessage());
try {
Os.unlink(profileFile.getAbsolutePath());
} catch (ErrnoException unlinkErr) {
- Log.v(TAG, "Unable to unlink jit profile file " + profileFile, unlinkErr);
+ if (unlinkErr.errno != OsConstants.ENOENT) {
+ Log.v(TAG, "Unable to unlink jit profile file "
+ + profileFile + ": " + unlinkErr.getMessage());
+ }
}
return;
} finally {
@@ -4886,6 +4981,9 @@
DdmVmInternal.enableRecentAllocations(true);
}
+ // Note when this process has started.
+ Process.setStartTimes(SystemClock.elapsedRealtime(), SystemClock.uptimeMillis());
+
mBoundApplication = data;
mConfiguration = new Configuration(data.config);
mCompatConfiguration = new Configuration(data.config);
diff --git a/core/java/android/app/AlarmManager.java b/core/java/android/app/AlarmManager.java
index b569416..455f869 100644
--- a/core/java/android/app/AlarmManager.java
+++ b/core/java/android/app/AlarmManager.java
@@ -201,6 +201,7 @@
try {
mService.remove(null, this);
} catch (RemoteException ex) {
+ throw ex.rethrowFromSystemServer();
}
synchronized (AlarmManager.class) {
@@ -656,6 +657,7 @@
mService.set(mPackageName, type, triggerAtMillis, windowMillis, intervalMillis, flags,
operation, recipientWrapper, listenerTag, workSource, alarmClock);
} catch (RemoteException ex) {
+ throw ex.rethrowFromSystemServer();
}
}
@@ -886,6 +888,7 @@
try {
mService.remove(operation, null);
} catch (RemoteException ex) {
+ throw ex.rethrowFromSystemServer();
}
}
@@ -926,6 +929,7 @@
try {
mService.setTime(millis);
} catch (RemoteException ex) {
+ throw ex.rethrowFromSystemServer();
}
}
@@ -965,6 +969,7 @@
try {
mService.setTimeZone(timeZone);
} catch (RemoteException ex) {
+ throw ex.rethrowFromSystemServer();
}
}
@@ -973,7 +978,7 @@
try {
return mService.getNextWakeFromIdleTime();
} catch (RemoteException ex) {
- return Long.MAX_VALUE;
+ throw ex.rethrowFromSystemServer();
}
}
@@ -1005,7 +1010,7 @@
try {
return mService.getNextAlarmClock(userId);
} catch (RemoteException ex) {
- return null;
+ throw ex.rethrowFromSystemServer();
}
}
diff --git a/core/java/android/app/ApplicationLoaders.java b/core/java/android/app/ApplicationLoaders.java
index b20c091..0fc097e 100644
--- a/core/java/android/app/ApplicationLoaders.java
+++ b/core/java/android/app/ApplicationLoaders.java
@@ -86,6 +86,18 @@
String libraryPermittedPath,
boolean isShared);
+ /**
+ * Adds a new path the classpath of the given loader.
+ * @throws IllegalStateException if the provided class loader is not a {@link PathClassLoader}.
+ */
+ void addPath(ClassLoader classLoader, String dexPath) {
+ if (!(classLoader instanceof PathClassLoader)) {
+ throw new IllegalStateException("class loader is not a PathClassLoader");
+ }
+ final PathClassLoader baseDexClassLoader = (PathClassLoader) classLoader;
+ baseDexClassLoader.addDexPath(dexPath);
+ }
+
private final ArrayMap<String, ClassLoader> mLoaders = new ArrayMap<String, ClassLoader>();
private static final ApplicationLoaders gApplicationLoaders
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index 53cc9ca..38f32f7 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -1093,6 +1093,14 @@
}
@Override
+ public Drawable getManagedUserBadgedDrawable(Drawable drawable, Rect badgeLocation,
+ int badgeDensity) {
+ Drawable badgeDrawable = getDrawableForDensity(
+ com.android.internal.R.drawable.ic_corp_badge, badgeDensity);
+ return getBadgedDrawable(drawable, badgeDrawable, badgeLocation, true);
+ }
+
+ @Override
public Drawable getUserBadgedIcon(Drawable icon, UserHandle user) {
final int badgeResId = getBadgeResIdForUser(user.getIdentifier());
if (badgeResId == 0) {
@@ -1114,24 +1122,27 @@
@Override
public Drawable getUserBadgeForDensity(UserHandle user, int density) {
- return getManagedProfileIconForDensity(user, density,
- com.android.internal.R.drawable.ic_corp_badge);
+ return getManagedProfileIconForDensity(user, com.android.internal.R.drawable.ic_corp_badge,
+ density);
}
@Override
public Drawable getUserBadgeForDensityNoBackground(UserHandle user, int density) {
- return getManagedProfileIconForDensity(user, density,
- com.android.internal.R.drawable.ic_corp_badge_no_background);
+ return getManagedProfileIconForDensity(user,
+ com.android.internal.R.drawable.ic_corp_badge_no_background, density);
}
- private Drawable getManagedProfileIconForDensity(UserHandle user, int density,
- int drawableId) {
+ private Drawable getDrawableForDensity(int drawableId, int density) {
+ if (density <= 0) {
+ density = mContext.getResources().getDisplayMetrics().densityDpi;
+ }
+ return Resources.getSystem().getDrawableForDensity(drawableId, density);
+ }
+
+ private Drawable getManagedProfileIconForDensity(UserHandle user, int drawableId, int density) {
UserInfo userInfo = getUserIfProfile(user.getIdentifier());
if (userInfo != null && userInfo.isManagedProfile()) {
- if (density <= 0) {
- density = mContext.getResources().getDisplayMetrics().densityDpi;
- }
- return Resources.getSystem().getDrawableForDensity(drawableId, density);
+ return getDrawableForDensity(drawableId, density);
}
return null;
}
@@ -1532,9 +1543,9 @@
}
@Override
- public void verifyIntentFilter(int id, int verificationCode, List<String> outFailedDomains) {
+ public void verifyIntentFilter(int id, int verificationCode, List<String> failedDomains) {
try {
- mPM.verifyIntentFilter(id, verificationCode, outFailedDomains);
+ mPM.verifyIntentFilter(id, verificationCode, failedDomains);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 47eec8b..e76f991 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -396,9 +396,11 @@
/**
* Try our best to migrate all files from source to target that match
- * requested prefix. Return false if we have any trouble migrating.
+ * requested prefix.
+ *
+ * @return the number of files moved, or -1 if there was trouble.
*/
- private static boolean migrateFiles(File sourceDir, File targetDir, final String prefix) {
+ private static int migrateFiles(File sourceDir, File targetDir, final String prefix) {
final File[] sourceFiles = FileUtils.listFilesOrEmpty(sourceDir, new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
@@ -406,7 +408,7 @@
}
});
- boolean res = true;
+ int res = 0;
for (File sourceFile : sourceFiles) {
final File targetFile = new File(targetDir, sourceFile.getName());
Log.d(TAG, "Migrating " + sourceFile + " to " + targetFile);
@@ -416,9 +418,12 @@
if (!sourceFile.delete()) {
throw new IOException("Failed to clean up " + sourceFile);
}
+ if (res != -1) {
+ res++;
+ }
} catch (IOException e) {
Log.w(TAG, "Failed to migrate " + sourceFile + ": " + e);
- res = false;
+ res = -1;
}
}
return res;
@@ -430,12 +435,17 @@
final File source = sourceContext.getSharedPreferencesPath(name);
final File target = getSharedPreferencesPath(name);
- // Evict any in-memory caches for either location
- final ArrayMap<File, SharedPreferencesImpl> cache = getSharedPreferencesCacheLocked();
- cache.remove(source);
- cache.remove(target);
-
- return migrateFiles(source.getParentFile(), target.getParentFile(), source.getName());
+ final int res = migrateFiles(source.getParentFile(), target.getParentFile(),
+ source.getName());
+ if (res > 0) {
+ // We moved at least one file, so evict any in-memory caches for
+ // either location
+ final ArrayMap<File, SharedPreferencesImpl> cache =
+ getSharedPreferencesCacheLocked();
+ cache.remove(source);
+ cache.remove(target);
+ }
+ return res != -1;
}
}
@@ -675,7 +685,8 @@
synchronized (ContextImpl.class) {
final File source = sourceContext.getDatabasePath(name);
final File target = getDatabasePath(name);
- return migrateFiles(source.getParentFile(), target.getParentFile(), source.getName());
+ return migrateFiles(source.getParentFile(), target.getParentFile(),
+ source.getName()) != -1;
}
}
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index 4bfd049..70bff80 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -143,7 +143,7 @@
public boolean moveActivityTaskToBack(IBinder token, boolean nonRoot) throws RemoteException;
public void moveTaskBackwards(int task) throws RemoteException;
public void moveTaskToStack(int taskId, int stackId, boolean toTop) throws RemoteException;
- public void moveTaskToDockedStack(int taskId, int createMode, boolean toTop, boolean animate,
+ public boolean moveTaskToDockedStack(int taskId, int createMode, boolean toTop, boolean animate,
Rect initialBounds) throws RemoteException;
public boolean moveTopActivityToPinnedStack(int stackId, Rect bounds) throws RemoteException;
public void resizeStack(int stackId, Rect bounds, boolean allowResizeInDockedMode,
@@ -171,6 +171,16 @@
public void resizeDockedStack(Rect dockedBounds, Rect tempDockedTaskBounds,
Rect tempDockedTaskInsetBounds,
Rect tempOtherTaskBounds, Rect tempOtherTaskInsetBounds) throws RemoteException;
+ /**
+ * Resizes the pinned stack.
+ *
+ * @param pinnedBounds The bounds for the pinned stack.
+ * @param tempPinnedTaskBounds The temporary bounds for the tasks in the pinned stack, which
+ * might be different from the stack bounds to allow more
+ * flexibility while resizing, or {@code null} if they should be the
+ * same as the stack bounds.
+ */
+ public void resizePinnedStack(Rect pinnedBounds, Rect tempPinnedTaskBounds) throws RemoteException;
public void positionTaskInStack(int taskId, int stackId, int position) throws RemoteException;
public List<StackInfo> getAllStackInfos() throws RemoteException;
public StackInfo getStackInfo(int stackId) throws RemoteException;
@@ -982,4 +992,5 @@
int REMOVE_STACK = IBinder.FIRST_CALL_TRANSACTION + 367;
int SET_LENIENT_BACKGROUND_CHECK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+368;
int GET_MEMORY_TRIM_LEVEL_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+369;
+ int RESIZE_PINNED_STACK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 370;
}
diff --git a/core/java/android/app/IApplicationThread.java b/core/java/android/app/IApplicationThread.java
index a3c9591..628bde0 100644
--- a/core/java/android/app/IApplicationThread.java
+++ b/core/java/android/app/IApplicationThread.java
@@ -123,8 +123,13 @@
void dumpHeap(boolean managed, String path, ParcelFileDescriptor fd)
throws RemoteException;
void setSchedulingGroup(int group) throws RemoteException;
+ // the package has been removed, clean up internal references
static final int PACKAGE_REMOVED = 0;
static final int EXTERNAL_STORAGE_UNAVAILABLE = 1;
+ // the package is being modified in-place, don't kill it and retain references to it
+ static final int PACKAGE_REMOVED_DONT_KILL = 2;
+ // a previously removed package was replaced with a new version [eg. upgrade, split added, ...]
+ static final int PACKAGE_REPLACED = 3;
void dispatchPackageBroadcast(int cmd, String[] packages) throws RemoteException;
void scheduleCrash(String msg) throws RemoteException;
void dumpActivity(FileDescriptor fd, IBinder servicetoken, String prefix, String[] args)
diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java
index b65faa9..cd17078 100644
--- a/core/java/android/app/LoadedApk.java
+++ b/core/java/android/app/LoadedApk.java
@@ -58,6 +58,7 @@
import java.net.URL;
import java.util.List;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collections;
import java.util.Enumeration;
import java.util.Objects;
@@ -83,24 +84,25 @@
private static final String TAG = "LoadedApk";
private final ActivityThread mActivityThread;
- private ApplicationInfo mApplicationInfo;
final String mPackageName;
- private final String mAppDir;
- private final String mResDir;
- private final String[] mSplitAppDirs;
- private final String[] mSplitResDirs;
- private final String[] mOverlayDirs;
- private final String[] mSharedLibraries;
- private final String mDataDir;
- private final String mLibDir;
- private final File mDataDirFile;
- private final File mDeviceEncryptedDataDirFile;
- private final File mCredentialEncryptedDataDirFile;
+ private ApplicationInfo mApplicationInfo;
+ private String mAppDir;
+ private String mResDir;
+ private String[] mSplitAppDirs;
+ private String[] mSplitResDirs;
+ private String[] mOverlayDirs;
+ private String[] mSharedLibraries;
+ private String mDataDir;
+ private String mLibDir;
+ private File mDataDirFile;
+ private File mDeviceEncryptedDataDirFile;
+ private File mCredentialEncryptedDataDirFile;
private final ClassLoader mBaseClassLoader;
private final boolean mSecurityViolation;
private final boolean mIncludeCode;
private final boolean mRegisterPackage;
private final DisplayAdjustments mDisplayAdjustments = new DisplayAdjustments();
+ /** WARNING: This may change. Don't hold external references to it. */
Resources mResources;
private ClassLoader mClassLoader;
private Application mApplication;
@@ -129,23 +131,10 @@
public LoadedApk(ActivityThread activityThread, ApplicationInfo aInfo,
CompatibilityInfo compatInfo, ClassLoader baseLoader,
boolean securityViolation, boolean includeCode, boolean registerPackage) {
- final int myUid = Process.myUid();
- aInfo = adjustNativeLibraryPaths(aInfo);
mActivityThread = activityThread;
- mApplicationInfo = aInfo;
+ setApplicationInfo(aInfo);
mPackageName = aInfo.packageName;
- mAppDir = aInfo.sourceDir;
- mResDir = aInfo.uid == myUid ? aInfo.sourceDir : aInfo.publicSourceDir;
- mSplitAppDirs = aInfo.splitSourceDirs;
- mSplitResDirs = aInfo.uid == myUid ? aInfo.splitSourceDirs : aInfo.splitPublicSourceDirs;
- mOverlayDirs = aInfo.resourceDirs;
- mSharedLibraries = aInfo.sharedLibraryFiles;
- mDataDir = aInfo.dataDir;
- mDataDirFile = FileUtils.newFileOrNull(mDataDir);
- mDeviceEncryptedDataDirFile = FileUtils.newFileOrNull(aInfo.deviceEncryptedDataDir);
- mCredentialEncryptedDataDirFile = FileUtils.newFileOrNull(aInfo.credentialEncryptedDataDir);
- mLibDir = aInfo.nativeLibraryDir;
mBaseClassLoader = baseLoader;
mSecurityViolation = securityViolation;
mIncludeCode = includeCode;
@@ -266,26 +255,165 @@
return ai.sharedLibraryFiles;
}
- public ClassLoader getClassLoader() {
- synchronized (this) {
- if (mClassLoader != null) {
- return mClassLoader;
- }
+ public void updateApplicationInfo(ApplicationInfo aInfo, List<String> oldPaths) {
+ setApplicationInfo(aInfo);
- if (mPackageName.equals("android")) {
- if (mBaseClassLoader == null) {
- mClassLoader = ClassLoader.getSystemClassLoader();
- } else {
- mClassLoader = mBaseClassLoader;
+ final List<String> newPaths = new ArrayList<>();
+ makePaths(mActivityThread, aInfo, newPaths, null /*libPaths*/);
+ final List<String> addedPaths = new ArrayList<>(newPaths.size());
+
+ if (oldPaths != null) {
+ for (String path : newPaths) {
+ final String apkName = path.substring(path.lastIndexOf(File.separator));
+ boolean match = false;
+ for (String oldPath : oldPaths) {
+ final String oldApkName = oldPath.substring(path.lastIndexOf(File.separator));
+ if (apkName.equals(oldApkName)) {
+ match = true;
+ break;
+ }
}
- return mClassLoader;
+ if (!match) {
+ addedPaths.add(path);
+ }
+ }
+ } else {
+ addedPaths.addAll(newPaths);
+ }
+ synchronized (this) {
+ mClassLoader = createOrUpdateClassLoaderLocked(addedPaths);
+ if (mResources != null) {
+ mResources = mActivityThread.getNewTopLevelResources(mResDir, mSplitResDirs,
+ mOverlayDirs, mApplicationInfo.sharedLibraryFiles, Display.DEFAULT_DISPLAY,
+ null /*overrideConfiguration*/, this);
+ }
+ }
+ }
+
+ private void setApplicationInfo(ApplicationInfo aInfo) {
+ final int myUid = Process.myUid();
+ aInfo = adjustNativeLibraryPaths(aInfo);
+ mApplicationInfo = aInfo;
+ mAppDir = aInfo.sourceDir;
+ mResDir = aInfo.uid == myUid ? aInfo.sourceDir : aInfo.publicSourceDir;
+ mSplitAppDirs = aInfo.splitSourceDirs;
+ mSplitResDirs = aInfo.uid == myUid ? aInfo.splitSourceDirs : aInfo.splitPublicSourceDirs;
+ mOverlayDirs = aInfo.resourceDirs;
+ mSharedLibraries = aInfo.sharedLibraryFiles;
+ mDataDir = aInfo.dataDir;
+ mLibDir = aInfo.nativeLibraryDir;
+ mDataDirFile = FileUtils.newFileOrNull(aInfo.dataDir);
+ mDeviceEncryptedDataDirFile = FileUtils.newFileOrNull(aInfo.deviceEncryptedDataDir);
+ mCredentialEncryptedDataDirFile = FileUtils.newFileOrNull(aInfo.credentialEncryptedDataDir);
+ }
+
+ public static void makePaths(ActivityThread activityThread, ApplicationInfo aInfo,
+ List<String> outZipPaths, List<String> outLibPaths) {
+ final String appDir = aInfo.sourceDir;
+ final String[] splitAppDirs = aInfo.splitSourceDirs;
+ final String libDir = aInfo.nativeLibraryDir;
+ final String[] sharedLibraries = aInfo.sharedLibraryFiles;
+
+ outZipPaths.clear();
+ outZipPaths.add(appDir);
+ if (splitAppDirs != null) {
+ Collections.addAll(outZipPaths, splitAppDirs);
+ }
+
+ if (outLibPaths != null) {
+ outLibPaths.clear();
+ }
+
+ /*
+ * The following is a bit of a hack to inject
+ * instrumentation into the system: If the app
+ * being started matches one of the instrumentation names,
+ * then we combine both the "instrumentation" and
+ * "instrumented" app into the path, along with the
+ * concatenation of both apps' shared library lists.
+ */
+
+ String instrumentationPackageName = activityThread.mInstrumentationPackageName;
+ String instrumentationAppDir = activityThread.mInstrumentationAppDir;
+ String[] instrumentationSplitAppDirs = activityThread.mInstrumentationSplitAppDirs;
+ String instrumentationLibDir = activityThread.mInstrumentationLibDir;
+
+ String instrumentedAppDir = activityThread.mInstrumentedAppDir;
+ String[] instrumentedSplitAppDirs = activityThread.mInstrumentedSplitAppDirs;
+ String instrumentedLibDir = activityThread.mInstrumentedLibDir;
+ String[] instrumentationLibs = null;
+
+ if (appDir.equals(instrumentationAppDir)
+ || appDir.equals(instrumentedAppDir)) {
+ outZipPaths.clear();
+ outZipPaths.add(instrumentationAppDir);
+ if (instrumentationSplitAppDirs != null) {
+ Collections.addAll(outZipPaths, instrumentationSplitAppDirs);
+ }
+ outZipPaths.add(instrumentedAppDir);
+ if (instrumentedSplitAppDirs != null) {
+ Collections.addAll(outZipPaths, instrumentedSplitAppDirs);
}
+ if (outLibPaths != null) {
+ outLibPaths.add(instrumentationLibDir);
+ outLibPaths.add(instrumentedLibDir);
+ }
+
+ if (!instrumentedAppDir.equals(instrumentationAppDir)) {
+ instrumentationLibs = getLibrariesFor(instrumentationPackageName);
+ }
+ }
+
+ if (outLibPaths != null) {
+ if (outLibPaths.isEmpty()) {
+ outLibPaths.add(libDir);
+ }
+
+ // Add path to libraries in apk for current abi. Do this now because more entries
+ // will be added to zipPaths that shouldn't be part of the library path.
+ if (aInfo.primaryCpuAbi != null) {
+ for (String apk : outZipPaths) {
+ outLibPaths.add(apk + "!/lib/" + aInfo.primaryCpuAbi);
+ }
+ }
+
+ if (aInfo.isSystemApp() && !aInfo.isUpdatedSystemApp()) {
+ // Add path to system libraries to libPaths;
+ // Access to system libs should be limited
+ // to bundled applications; this is why updated
+ // system apps are not included.
+ outLibPaths.add(System.getProperty("java.library.path"));
+ }
+ }
+
+ if (sharedLibraries != null) {
+ for (String lib : sharedLibraries) {
+ if (!outZipPaths.contains(lib)) {
+ outZipPaths.add(0, lib);
+ }
+ }
+ }
+
+ if (instrumentationLibs != null) {
+ for (String lib : instrumentationLibs) {
+ if (!outZipPaths.contains(lib)) {
+ outZipPaths.add(0, lib);
+ }
+ }
+ }
+
+ final String zip = TextUtils.join(File.pathSeparator, outZipPaths);
+ }
+
+ private ClassLoader createOrUpdateClassLoaderLocked(List<String> addedPaths) {
+ final ClassLoader classLoader;
+ if (mIncludeCode && !mPackageName.equals("android")) {
// Avoid the binder call when the package is the current application package.
// The activity manager will perform ensure that dexopt is performed before
// spinning up the process.
if (!Objects.equals(mPackageName, ActivityThread.currentPackageName())) {
- final String isa = VMRuntime.getRuntime().vmInstructionSet();
+ VMRuntime.getRuntime().vmInstructionSet();
try {
ActivityThread.getPackageManager().notifyPackageUse(mPackageName);
} catch (RemoteException re) {
@@ -294,7 +422,6 @@
}
final List<String> zipPaths = new ArrayList<>();
- final List<String> apkPaths = new ArrayList<>();
final List<String> libPaths = new ArrayList<>();
if (mRegisterPackage) {
@@ -305,91 +432,12 @@
}
}
- zipPaths.add(mAppDir);
- if (mSplitAppDirs != null) {
- Collections.addAll(zipPaths, mSplitAppDirs);
- }
-
- libPaths.add(mLibDir);
-
- /*
- * The following is a bit of a hack to inject
- * instrumentation into the system: If the app
- * being started matches one of the instrumentation names,
- * then we combine both the "instrumentation" and
- * "instrumented" app into the path, along with the
- * concatenation of both apps' shared library lists.
- */
-
- String instrumentationPackageName = mActivityThread.mInstrumentationPackageName;
- String instrumentationAppDir = mActivityThread.mInstrumentationAppDir;
- String[] instrumentationSplitAppDirs = mActivityThread.mInstrumentationSplitAppDirs;
- String instrumentationLibDir = mActivityThread.mInstrumentationLibDir;
-
- String instrumentedAppDir = mActivityThread.mInstrumentedAppDir;
- String[] instrumentedSplitAppDirs = mActivityThread.mInstrumentedSplitAppDirs;
- String instrumentedLibDir = mActivityThread.mInstrumentedLibDir;
- String[] instrumentationLibs = null;
-
- if (mAppDir.equals(instrumentationAppDir)
- || mAppDir.equals(instrumentedAppDir)) {
- zipPaths.clear();
- zipPaths.add(instrumentationAppDir);
- if (instrumentationSplitAppDirs != null) {
- Collections.addAll(zipPaths, instrumentationSplitAppDirs);
- }
- zipPaths.add(instrumentedAppDir);
- if (instrumentedSplitAppDirs != null) {
- Collections.addAll(zipPaths, instrumentedSplitAppDirs);
- }
-
- libPaths.clear();
- libPaths.add(instrumentationLibDir);
- libPaths.add(instrumentedLibDir);
-
- if (!instrumentedAppDir.equals(instrumentationAppDir)) {
- instrumentationLibs = getLibrariesFor(instrumentationPackageName);
- }
- }
-
- apkPaths.addAll(zipPaths);
-
- if (mSharedLibraries != null) {
- for (String lib : mSharedLibraries) {
- if (!zipPaths.contains(lib)) {
- zipPaths.add(0, lib);
- }
- }
- }
-
- if (instrumentationLibs != null) {
- for (String lib : instrumentationLibs) {
- if (!zipPaths.contains(lib)) {
- zipPaths.add(0, lib);
- }
- }
- }
-
- final String zip = mIncludeCode ? TextUtils.join(File.pathSeparator, zipPaths) : "";
-
- // Add path to libraries in apk for current abi
- if (mApplicationInfo.primaryCpuAbi != null) {
- for (String apk : apkPaths) {
- libPaths.add(apk + "!/lib/" + mApplicationInfo.primaryCpuAbi);
- }
- }
-
+ makePaths(mActivityThread, mApplicationInfo, zipPaths, libPaths);
+ final String zip = TextUtils.join(File.pathSeparator, zipPaths);
+ final boolean isBundledApp = mApplicationInfo.isSystemApp()
+ && !mApplicationInfo.isUpdatedSystemApp();
String libraryPermittedPath = mDataDir;
- boolean isBundledApp = false;
-
- if (mApplicationInfo.isSystemApp() && !mApplicationInfo.isUpdatedSystemApp()) {
- isBundledApp = true;
- // Add path to system libraries to libPaths;
- // Access to system libs should be limited
- // to bundled applications; this is why updated
- // system apps are not included.
- libPaths.add(System.getProperty("java.library.path"));
-
+ if (isBundledApp) {
// This is necessary to grant bundled apps access to
// libraries located in subdirectories of /system/lib
libraryPermittedPath += File.pathSeparator +
@@ -414,15 +462,42 @@
Slog.v(ActivityThread.TAG, "Class path: " + zip +
", JNI path: " + librarySearchPath);
- // Temporarily disable logging of disk reads on the Looper thread
- // as this is early and necessary.
- StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
+ if (mClassLoader == null) {
+ // Temporarily disable logging of disk reads on the Looper thread
+ // as this is early and necessary.
+ StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
- mClassLoader = ApplicationLoaders.getDefault().getClassLoader(zip,
- mApplicationInfo.targetSdkVersion, isBundledApp, librarySearchPath,
- libraryPermittedPath, mBaseClassLoader);
+ classLoader = ApplicationLoaders.getDefault().getClassLoader(zip,
+ mApplicationInfo.targetSdkVersion, isBundledApp, librarySearchPath,
+ libraryPermittedPath, mBaseClassLoader);
- StrictMode.setThreadPolicy(oldPolicy);
+ StrictMode.setThreadPolicy(oldPolicy);
+ } else if (addedPaths != null && addedPaths.size() > 0) {
+ final String add = TextUtils.join(File.pathSeparator, addedPaths);
+ ApplicationLoaders.getDefault().addPath(mClassLoader, add);
+ classLoader = mClassLoader;
+ } else {
+ classLoader = mClassLoader;
+ }
+ } else {
+ if (mClassLoader == null) {
+ if (mBaseClassLoader == null) {
+ classLoader = ClassLoader.getSystemClassLoader();
+ } else {
+ classLoader = mBaseClassLoader;
+ }
+ } else {
+ classLoader = mClassLoader;
+ }
+ }
+ return classLoader;
+ }
+
+ public ClassLoader getClassLoader() {
+ synchronized (this) {
+ if (mClassLoader == null) {
+ mClassLoader = createOrUpdateClassLoaderLocked(null /*addedPaths*/);
+ }
return mClassLoader;
}
}
@@ -1103,7 +1178,6 @@
private RuntimeException mUnbindLocation;
- private boolean mDied;
private boolean mForgotten;
private static class ConnectionInfo {
@@ -1202,7 +1276,6 @@
ServiceDispatcher.ConnectionInfo old;
synchronized (this) {
- mDied = true;
old = mActiveConnections.remove(name);
if (old == null || old.binder != service) {
// Death for someone different than who we last
@@ -1237,7 +1310,6 @@
if (service != null) {
// A new service is being connected... set it all up.
- mDied = false;
info = new ConnectionInfo();
info.binder = service;
info.deathMonitor = new DeathMonitor(name, service);
diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java
index b6448ee..057a4e9 100644
--- a/core/java/android/app/NotificationManager.java
+++ b/core/java/android/app/NotificationManager.java
@@ -890,9 +890,8 @@
final List<StatusBarNotification> list = parceledList.getList();
return list.toArray(new StatusBarNotification[list.size()]);
} catch (RemoteException e) {
- Log.e(TAG, "Unable to talk to notification manager. Woe!", e);
+ throw e.rethrowFromSystemServer();
}
- return new StatusBarNotification[0];
}
/**
@@ -913,9 +912,8 @@
try {
return zenModeToInterruptionFilter(service.getZenMode());
} catch (RemoteException e) {
- Log.e(TAG, "Unable to talk to notification manager. Woe!", e);
+ throw e.rethrowFromSystemServer();
}
- return INTERRUPTION_FILTER_UNKNOWN;
}
/**
@@ -936,7 +934,7 @@
try {
service.setInterruptionFilter(mContext.getOpPackageName(), interruptionFilter);
} catch (RemoteException e) {
- Log.e(TAG, "Unable to talk to notification manager. Woe!", e);
+ throw e.rethrowFromSystemServer();
}
}
diff --git a/core/java/android/app/ResourcesManager.java b/core/java/android/app/ResourcesManager.java
index 94e584e..bc44553d 100644
--- a/core/java/android/app/ResourcesManager.java
+++ b/core/java/android/app/ResourcesManager.java
@@ -23,6 +23,7 @@
import android.content.res.CompatibilityInfo;
import android.content.res.Configuration;
import android.content.res.Resources;
+import android.content.res.ResourcesImpl;
import android.content.res.ResourcesKey;
import android.hardware.display.DisplayManagerGlobal;
import android.util.ArrayMap;
@@ -250,7 +251,8 @@
} else {
config = getConfiguration();
}
- r = new Resources(assets, dm, config, compatInfo, classLoader);
+ r = new Resources(classLoader);
+ r.setImpl(new ResourcesImpl(assets, dm, config, compatInfo));
if (DEBUG) Slog.i(TAG, "Created app resources " + resDir + " " + r + ": "
+ r.getConfiguration() + " appScale=" + r.getCompatibilityInfo().applicationScale);
@@ -288,6 +290,19 @@
}
}
+ /**
+ * Removes the top level Resources for applications with the given compatibility info.
+ * @see #getTopLevelResources(String, String[], String[], String[], int, Configuration, CompatibilityInfo, ClassLoader)
+ */
+ void removeTopLevelResources(String resDir, int displayId, Configuration overrideConfiguration,
+ CompatibilityInfo compatInfo) {
+ final float scale = compatInfo.applicationScale;
+ final Configuration overrideConfigCopy = (overrideConfiguration != null)
+ ? new Configuration(overrideConfiguration) : null;
+ final ResourcesKey key = new ResourcesKey(resDir, displayId, overrideConfigCopy, scale);
+ mActiveResources.remove(key);
+ }
+
/* package */ void setDefaultLocalesLocked(LocaleList locales) {
final int bestLocale;
if (mHasNonSystemLocales) {
diff --git a/core/java/android/app/SearchManager.java b/core/java/android/app/SearchManager.java
index 9e32164..ac4abf5 100644
--- a/core/java/android/app/SearchManager.java
+++ b/core/java/android/app/SearchManager.java
@@ -686,8 +686,7 @@
try {
return mService.getGlobalSearchActivities();
} catch (RemoteException ex) {
- Log.e(TAG, "getGlobalSearchActivities() failed: " + ex);
- return null;
+ throw ex.rethrowFromSystemServer();
}
}
@@ -698,8 +697,7 @@
try {
return mService.getGlobalSearchActivity();
} catch (RemoteException ex) {
- Log.e(TAG, "getGlobalSearchActivity() failed: " + ex);
- return null;
+ throw ex.rethrowFromSystemServer();
}
}
@@ -716,8 +714,7 @@
try {
return mService.getWebSearchActivity();
} catch (RemoteException ex) {
- Log.e(TAG, "getWebSearchActivity() failed: " + ex);
- return null;
+ throw ex.rethrowFromSystemServer();
}
}
@@ -850,8 +847,7 @@
try {
return mService.getSearchableInfo(componentName);
} catch (RemoteException ex) {
- Log.e(TAG, "getSearchableInfo() failed: " + ex);
- return null;
+ throw ex.rethrowFromSystemServer();
}
}
@@ -935,8 +931,7 @@
try {
return mService.getSearchablesInGlobalSearch();
} catch (RemoteException e) {
- Log.e(TAG, "getSearchablesInGlobalSearch() failed: " + e);
- return null;
+ throw e.rethrowFromSystemServer();
}
}
@@ -958,8 +953,7 @@
}
return intent;
} catch (RemoteException re) {
- Log.e(TAG, "getAssistIntent() failed: " + re);
- return null;
+ throw re.rethrowFromSystemServer();
}
}
@@ -977,7 +971,7 @@
}
mService.launchAssist(args);
} catch (RemoteException re) {
- Log.e(TAG, "launchAssist() failed: " + re);
+ throw re.rethrowFromSystemServer();
}
}
@@ -995,8 +989,7 @@
}
return mService.launchLegacyAssist(hint, userHandle, args);
} catch (RemoteException re) {
- Log.e(TAG, "launchAssist() failed: " + re);
- return false;
+ throw re.rethrowFromSystemServer();
}
}
}
diff --git a/core/java/android/app/StatusBarManager.java b/core/java/android/app/StatusBarManager.java
index b899116..e57a9b5 100644
--- a/core/java/android/app/StatusBarManager.java
+++ b/core/java/android/app/StatusBarManager.java
@@ -123,8 +123,7 @@
svc.disable(what, mToken, mContext.getPackageName());
}
} catch (RemoteException ex) {
- // system process is dead anyway.
- throw new RuntimeException(ex);
+ throw ex.rethrowFromSystemServer();
}
}
@@ -141,8 +140,7 @@
svc.disable2(what, mToken, mContext.getPackageName());
}
} catch (RemoteException ex) {
- // system process is dead anyway.
- throw new RuntimeException(ex);
+ throw ex.rethrowFromSystemServer();
}
}
@@ -156,8 +154,7 @@
svc.expandNotificationsPanel();
}
} catch (RemoteException ex) {
- // system process is dead anyway.
- throw new RuntimeException(ex);
+ throw ex.rethrowFromSystemServer();
}
}
@@ -171,8 +168,7 @@
svc.collapsePanels();
}
} catch (RemoteException ex) {
- // system process is dead anyway.
- throw new RuntimeException(ex);
+ throw ex.rethrowFromSystemServer();
}
}
@@ -193,8 +189,7 @@
svc.expandSettingsPanel(subPanel);
}
} catch (RemoteException ex) {
- // system process is dead anyway.
- throw new RuntimeException(ex);
+ throw ex.rethrowFromSystemServer();
}
}
@@ -206,8 +201,7 @@
contentDescription);
}
} catch (RemoteException ex) {
- // system process is dead anyway.
- throw new RuntimeException(ex);
+ throw ex.rethrowFromSystemServer();
}
}
@@ -218,8 +212,7 @@
svc.removeIcon(slot);
}
} catch (RemoteException ex) {
- // system process is dead anyway.
- throw new RuntimeException(ex);
+ throw ex.rethrowFromSystemServer();
}
}
@@ -230,8 +223,7 @@
svc.setIconVisibility(slot, visible);
}
} catch (RemoteException ex) {
- // system process is dead anyway.
- throw new RuntimeException(ex);
+ throw ex.rethrowFromSystemServer();
}
}
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index 307c3eb..b1c5fd8 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -226,7 +226,7 @@
SYSTEM_SERVICE_NAMES.put(android.text.ClipboardManager.class, Context.CLIPBOARD_SERVICE);
registerService(Context.CONNECTIVITY_SERVICE, ConnectivityManager.class,
- new StaticOuterContextServiceFetcher<ConnectivityManager>() {
+ new StaticApplicationContextServiceFetcher<ConnectivityManager>() {
@Override
public ConnectivityManager createService(Context context) {
IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE);
@@ -840,22 +840,21 @@
}
/**
- * Like StaticServiceFetcher, creates only one instance of the service per process, but when
- * creating the service for the first time, passes it the outer context of the creating
- * component.
+ * Like StaticServiceFetcher, creates only one instance of the service per application, but when
+ * creating the service for the first time, passes it the application context of the creating
+ * application.
*
- * TODO: Is this safe in the case where multiple applications share the same process?
* TODO: Delete this once its only user (ConnectivityManager) is known to work well in the
* case where multiple application components each have their own ConnectivityManager object.
*/
- static abstract class StaticOuterContextServiceFetcher<T> implements ServiceFetcher<T> {
+ static abstract class StaticApplicationContextServiceFetcher<T> implements ServiceFetcher<T> {
private T mCachedInstance;
@Override
public final T getService(ContextImpl ctx) {
- synchronized (StaticOuterContextServiceFetcher.this) {
+ synchronized (StaticApplicationContextServiceFetcher.this) {
if (mCachedInstance == null) {
- mCachedInstance = createService(ctx.getOuterContext());
+ mCachedInstance = createService(ctx.getApplicationContext());
}
return mCachedInstance;
}
diff --git a/core/java/android/app/UiModeManager.java b/core/java/android/app/UiModeManager.java
index 56b4249..69e8df8 100644
--- a/core/java/android/app/UiModeManager.java
+++ b/core/java/android/app/UiModeManager.java
@@ -17,6 +17,7 @@
package android.app;
import android.annotation.IntDef;
+import android.annotation.TestApi;
import android.content.Context;
import android.content.res.Configuration;
import android.os.RemoteException;
@@ -158,7 +159,7 @@
try {
mService.enableCarMode(flags);
} catch (RemoteException e) {
- Log.e(TAG, "disableCarMode: RemoteException", e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -181,7 +182,7 @@
try {
mService.disableCarMode(flags);
} catch (RemoteException e) {
- Log.e(TAG, "disableCarMode: RemoteException", e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -200,7 +201,7 @@
try {
return mService.getCurrentModeType();
} catch (RemoteException e) {
- Log.e(TAG, "getCurrentModeType: RemoteException", e);
+ throw e.rethrowFromSystemServer();
}
}
return Configuration.UI_MODE_TYPE_NORMAL;
@@ -233,7 +234,7 @@
try {
mService.setNightMode(mode);
} catch (RemoteException e) {
- Log.e(TAG, "setNightMode: RemoteException", e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -257,7 +258,7 @@
try {
return mService.getNightMode();
} catch (RemoteException e) {
- Log.e(TAG, "getNightMode: RemoteException", e);
+ throw e.rethrowFromSystemServer();
}
}
return -1;
@@ -266,13 +267,15 @@
/**
* @return If UI mode is locked or not. When UI mode is locked, calls to change UI mode
* like {@link #enableCarMode(int)} will silently fail.
+ * @hide
*/
+ @TestApi
public boolean isUiModeLocked() {
if (mService != null) {
try {
return mService.isUiModeLocked();
} catch (RemoteException e) {
- Log.e(TAG, "isUiModeLocked: RemoteException", e);
+ throw e.rethrowFromSystemServer();
}
}
return true;
@@ -286,13 +289,15 @@
* mode will fail silently.
*
* @return {@code true} if night mode is locked or {@code false} otherwise
+ * @hide
*/
+ @TestApi
public boolean isNightModeLocked() {
if (mService != null) {
try {
return mService.isNightModeLocked();
} catch (RemoteException e) {
- Log.e(TAG, "isNightModeLocked: RemoteException", e);
+ throw e.rethrowFromSystemServer();
}
}
return true;
diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java
index b7e31ab..6bc03f7 100644
--- a/core/java/android/app/WallpaperManager.java
+++ b/core/java/android/app/WallpaperManager.java
@@ -293,7 +293,7 @@
return null;
}
} catch (RemoteException e) {
- // Ignore
+ throw e.rethrowFromSystemServer();
}
}
if (mWallpaper != null) {
@@ -349,7 +349,7 @@
}
}
} catch (RemoteException e) {
- // Ignore
+ throw e.rethrowFromSystemServer();
}
return null;
}
@@ -691,7 +691,7 @@
Bundle outParams = new Bundle();
return sGlobals.mService.getWallpaper(null, which, outParams, userId);
} catch (RemoteException e) {
- return null;
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -720,7 +720,7 @@
return sGlobals.mService.getWallpaperInfo();
}
} catch (RemoteException e) {
- return null;
+ throw e.rethrowFromSystemServer();
}
}
@@ -844,7 +844,7 @@
}
}
} catch (RemoteException e) {
- // Ignore
+ throw e.rethrowFromSystemServer();
}
return result.getInt(EXTRA_NEW_WALLPAPER_ID, 0);
}
@@ -950,7 +950,7 @@
}
}
} catch (RemoteException e) {
- // Ignore
+ throw e.rethrowFromSystemServer();
}
return result.getInt(EXTRA_NEW_WALLPAPER_ID, 0);
}
@@ -1067,7 +1067,7 @@
}
}
} catch (RemoteException e) {
- // Ignore
+ throw e.rethrowFromSystemServer();
}
return result.getInt(EXTRA_NEW_WALLPAPER_ID, 0);
@@ -1088,7 +1088,7 @@
String name = "res:" + resources.getResourceName(resid);
return sGlobals.mService.hasNamedWallpaper(name);
} catch (RemoteException e) {
- return false;
+ throw e.rethrowFromSystemServer();
}
}
@@ -1114,8 +1114,7 @@
try {
return sGlobals.mService.getWidthHint();
} catch (RemoteException e) {
- // Shouldn't happen!
- return 0;
+ throw e.rethrowFromSystemServer();
}
}
@@ -1141,8 +1140,7 @@
try {
return sGlobals.mService.getHeightHint();
} catch (RemoteException e) {
- // Shouldn't happen!
- return 0;
+ throw e.rethrowFromSystemServer();
}
}
@@ -1203,7 +1201,7 @@
mContext.getOpPackageName());
}
} catch (RemoteException e) {
- // Ignore
+ throw e.rethrowFromSystemServer();
}
}
@@ -1224,7 +1222,7 @@
sGlobals.mService.setDisplayPadding(padding, mContext.getOpPackageName());
}
} catch (RemoteException e) {
- // Ignore
+ throw e.rethrowFromSystemServer();
}
}
@@ -1245,7 +1243,7 @@
windowToken, x, y);
//Log.v(TAG, "...app returning after sending display offset!");
} catch (RemoteException e) {
- // Ignore.
+ throw e.rethrowFromSystemServer();
}
}
@@ -1274,7 +1272,7 @@
try {
sGlobals.mService.clearWallpaper(mContext.getOpPackageName(), which, userId);
} catch (RemoteException e) {
- // Ignore
+ throw e.rethrowFromSystemServer();
}
}
@@ -1296,9 +1294,8 @@
sGlobals.mService.setWallpaperComponentChecked(name, mContext.getOpPackageName());
return true;
} catch (RemoteException e) {
- // Ignore
+ throw e.rethrowFromSystemServer();
}
- return false;
}
/**
@@ -1321,7 +1318,7 @@
windowToken, xOffset, yOffset, mWallpaperXStep, mWallpaperYStep);
//Log.v(TAG, "...app returning after sending offsets!");
} catch (RemoteException e) {
- // Ignore.
+ throw e.rethrowFromSystemServer();
}
}
@@ -1359,7 +1356,7 @@
windowToken, action, x, y, z, extras, false);
//Log.v(TAG, "...app returning after sending offsets!");
} catch (RemoteException e) {
- // Ignore.
+ throw e.rethrowFromSystemServer();
}
}
@@ -1375,7 +1372,7 @@
try {
return sGlobals.mService.isWallpaperSupported(mContext.getOpPackageName());
} catch (RemoteException e) {
- // Ignore
+ throw e.rethrowFromSystemServer();
}
}
return false;
@@ -1395,7 +1392,7 @@
try {
return sGlobals.mService.isWallpaperSettingAllowed(mContext.getOpPackageName());
} catch (RemoteException e) {
- // Ignore
+ throw e.rethrowFromSystemServer();
}
}
return false;
@@ -1416,7 +1413,7 @@
WindowManagerGlobal.getWindowSession().setWallpaperPosition(
windowToken, -1, -1, -1, -1);
} catch (RemoteException e) {
- // Ignore.
+ throw e.rethrowFromSystemServer();
}
}
@@ -1436,6 +1433,25 @@
}
/**
+ * Remove one or more currently set wallpapers, reverting to the system default
+ * display for each one. If {@link #FLAG_SET_SYSTEM} is set in the {@code which}
+ * parameter, the intent {@link Intent#ACTION_WALLPAPER_CHANGED} will be broadcast
+ * upon success.
+ *
+ * @param which A bitwise combination of {@link #FLAG_SET_SYSTEM} or
+ * {@link #FLAG_SET_LOCK}
+ * @throws IOException If an error occurs reverting to the built-in wallpaper.
+ */
+ public void clear(int which) throws IOException {
+ if ((which & FLAG_SET_SYSTEM) != 0) {
+ clear();
+ }
+ if ((which & FLAG_SET_LOCK) != 0) {
+ clearWallpaper(FLAG_SET_LOCK, mContext.getUserId());
+ }
+ }
+
+ /**
* Open stream representing the default static image wallpaper.
*
* @hide
@@ -1497,9 +1513,8 @@
try {
return sGlobals.mService.setLockWallpaperCallback(callback);
} catch (RemoteException e) {
- Log.e(TAG, "Unable to contact wallpaper service");
+ throw e.rethrowFromSystemServer();
}
- return false;
}
// Private completion callback for setWallpaper() synchronization
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 6e29eaa..a1ad590 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -100,9 +100,6 @@
private final IDevicePolicyManager mService;
private final boolean mParentInstance;
- private static final String REMOTE_EXCEPTION_MESSAGE =
- "Failed to talk with device policy manager service";
-
private DevicePolicyManager(Context context, boolean parentInstance) {
this(context,
IDevicePolicyManager.Stub.asInterface(
@@ -989,7 +986,7 @@
try {
return mService.isAdminActive(admin, userId);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return false;
@@ -1004,7 +1001,7 @@
try {
return mService.isRemovingAdmin(admin, userId);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return false;
@@ -1029,7 +1026,7 @@
try {
return mService.getActiveAdmins(userId);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return null;
@@ -1054,7 +1051,7 @@
try {
return mService.packageHasActiveAdmins(packageName, userId);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return false;
@@ -1074,7 +1071,7 @@
try {
mService.removeActiveAdmin(admin, myUserId());
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -1093,7 +1090,7 @@
try {
return mService.hasGrantedPolicy(admin, usesPolicy, myUserId());
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return false;
@@ -1109,7 +1106,7 @@
try {
return mService.isSeparateProfileChallengeAllowed(userHandle);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return false;
@@ -1227,7 +1224,7 @@
try {
mService.setPasswordQuality(admin, quality, mParentInstance);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -1254,7 +1251,7 @@
try {
return mService.getPasswordQuality(admin, userHandle, mParentInstance);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return PASSWORD_QUALITY_UNSPECIFIED;
@@ -1291,7 +1288,7 @@
try {
mService.setPasswordMinimumLength(admin, length, mParentInstance);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -1319,7 +1316,7 @@
try {
return mService.getPasswordMinimumLength(admin, userHandle, mParentInstance);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return 0;
@@ -1357,7 +1354,7 @@
try {
mService.setPasswordMinimumUpperCase(admin, length, mParentInstance);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -1391,7 +1388,7 @@
try {
return mService.getPasswordMinimumUpperCase(admin, userHandle, mParentInstance);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return 0;
@@ -1429,7 +1426,7 @@
try {
mService.setPasswordMinimumLowerCase(admin, length, mParentInstance);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -1463,7 +1460,7 @@
try {
return mService.getPasswordMinimumLowerCase(admin, userHandle, mParentInstance);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return 0;
@@ -1500,7 +1497,7 @@
try {
mService.setPasswordMinimumLetters(admin, length, mParentInstance);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -1533,7 +1530,7 @@
try {
return mService.getPasswordMinimumLetters(admin, userHandle, mParentInstance);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return 0;
@@ -1570,7 +1567,7 @@
try {
mService.setPasswordMinimumNumeric(admin, length, mParentInstance);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -1603,7 +1600,7 @@
try {
return mService.getPasswordMinimumNumeric(admin, userHandle, mParentInstance);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return 0;
@@ -1640,7 +1637,7 @@
try {
mService.setPasswordMinimumSymbols(admin, length, mParentInstance);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -1672,7 +1669,7 @@
try {
return mService.getPasswordMinimumSymbols(admin, userHandle, mParentInstance);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return 0;
@@ -1709,7 +1706,7 @@
try {
mService.setPasswordMinimumNonLetter(admin, length, mParentInstance);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -1742,7 +1739,7 @@
try {
return mService.getPasswordMinimumNonLetter(admin, userHandle, mParentInstance);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return 0;
@@ -1780,7 +1777,7 @@
try {
mService.setPasswordHistoryLength(admin, length, mParentInstance);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -1816,7 +1813,7 @@
try {
mService.setPasswordExpirationTimeout(admin, timeout, mParentInstance);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -1840,7 +1837,7 @@
try {
return mService.getPasswordExpirationTimeout(admin, myUserId(), mParentInstance);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return 0;
@@ -1864,7 +1861,7 @@
try {
return mService.getPasswordExpiration(admin, myUserId(), mParentInstance);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return 0;
@@ -1893,7 +1890,7 @@
try {
return mService.getPasswordHistoryLength(admin, userHandle, mParentInstance);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return 0;
@@ -1931,7 +1928,7 @@
try {
return mService.isActivePasswordSufficient(myUserId(), mParentInstance);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return false;
@@ -1951,7 +1948,7 @@
try {
return mService.isProfileActivePasswordSufficientForParent(userHandle);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return false;
@@ -1988,7 +1985,7 @@
try {
return mService.getCurrentFailedPasswordAttempts(userHandle, mParentInstance);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return -1;
@@ -2005,7 +2002,7 @@
try {
return mService.getDoNotAskCredentialsOnBoot();
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return false;
@@ -2039,7 +2036,7 @@
try {
mService.setMaximumFailedPasswordsForWipe(admin, num, mParentInstance);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -2068,7 +2065,7 @@
return mService.getMaximumFailedPasswordsForWipe(
admin, userHandle, mParentInstance);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return 0;
@@ -2087,7 +2084,7 @@
return mService.getProfileWithMinimumFailedPasswordsForWipe(
userHandle, mParentInstance);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return UserHandle.USER_NULL;
@@ -2155,7 +2152,7 @@
try {
return mService.resetPassword(password, flags);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return false;
@@ -2183,7 +2180,7 @@
try {
mService.setMaximumTimeToLock(admin, timeMs, mParentInstance);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -2212,7 +2209,7 @@
try {
return mService.getMaximumTimeToLock(admin, userHandle, mParentInstance);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return 0;
@@ -2235,7 +2232,7 @@
try {
mService.lockNow(mParentInstance);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -2272,7 +2269,7 @@
try {
mService.wipeData(flags);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -2342,7 +2339,7 @@
}
return mService.setGlobalProxy(admin, hostSpec, exclSpec);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return null;
@@ -2370,7 +2367,7 @@
try {
mService.setRecommendedGlobalProxy(admin, proxyInfo);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -2386,7 +2383,7 @@
try {
return mService.getGlobalProxyAdmin(myUserId());
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return null;
@@ -2515,7 +2512,7 @@
try {
return mService.setStorageEncryption(admin, encrypt);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return ENCRYPTION_STATUS_UNSUPPORTED;
@@ -2535,7 +2532,7 @@
try {
return mService.getStorageEncryption(admin, myUserId());
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return false;
@@ -2570,7 +2567,7 @@
try {
return mService.getStorageEncryptionStatus(userHandle);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return ENCRYPTION_STATUS_UNSUPPORTED;
@@ -2591,7 +2588,7 @@
try {
return mService.installCaCert(admin, certBuffer);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return false;
@@ -2612,7 +2609,7 @@
} catch (CertificateException e) {
Log.w(TAG, "Unable to parse certificate", e);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -2640,7 +2637,7 @@
}
}
} catch (RemoteException re) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
+ throw re.rethrowFromSystemServer();
}
}
return certs;
@@ -2659,7 +2656,7 @@
mService.uninstallCaCerts(admin, new TrustedCertificateStore().userAliases()
.toArray(new String[0]));
} catch (RemoteException re) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
+ throw re.rethrowFromSystemServer();
}
}
}
@@ -2677,7 +2674,7 @@
mService.enforceCanManageCaCerts(admin);
return getCaCertAlias(certBuffer) != null;
} catch (RemoteException re) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
+ throw re.rethrowFromSystemServer();
} catch (CertificateException ce) {
Log.w(TAG, "Could not parse certificate", ce);
}
@@ -2737,7 +2734,7 @@
.getKeySpec(privKey, PKCS8EncodedKeySpec.class).getEncoded();
return mService.installKeyPair(admin, pkcs8Key, pemCert, alias, requestAccess);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
} catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
Log.w(TAG, "Failed to obtain private key material", e);
} catch (CertificateException | IOException e) {
@@ -2753,15 +2750,14 @@
* @param admin Which {@link DeviceAdminReceiver} this request is associated with, or
* {@code null} if calling from a delegated certificate installer.
* @param alias The private key alias under which the certificate is installed.
- * @return {@code true} if the keys were both removed, {@code false} otherwise.
+ * @return {@code true} if the certificate alias no longer exists, {@code false} otherwise.
*/
public boolean removeKeyPair(@Nullable ComponentName admin, @NonNull String alias) {
try {
return mService.removeKeyPair(admin, alias);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
- return false;
}
/**
@@ -2800,7 +2796,7 @@
try {
mService.setCertInstallerPackage(admin, installerPackage);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -2818,7 +2814,7 @@
try {
return mService.getCertInstallerPackage(admin);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return null;
@@ -2845,7 +2841,7 @@
try {
return mService.setAlwaysOnVpnPackage(admin, vpnPackage);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return false;
@@ -2865,7 +2861,7 @@
try {
return mService.getAlwaysOnVpnPackage(admin);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return null;
@@ -2890,7 +2886,7 @@
try {
mService.setCameraDisabled(admin, disabled);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -2911,7 +2907,7 @@
try {
return mService.getCameraDisabled(admin, userHandle);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return false;
@@ -2933,7 +2929,7 @@
try {
return mService.requestBugreport(admin);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return false;
@@ -2970,7 +2966,7 @@
try {
mService.setScreenCaptureDisabled(admin, disabled);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -2991,7 +2987,7 @@
try {
return mService.getScreenCaptureDisabled(admin, userHandle);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return false;
@@ -3014,7 +3010,7 @@
try {
mService.setAutoTimeRequired(admin, required);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -3027,7 +3023,7 @@
try {
return mService.getAutoTimeRequired();
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return false;
@@ -3052,7 +3048,7 @@
try {
mService.setForceEphemeralUsers(admin, forceEphemeralUsers);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -3066,7 +3062,7 @@
try {
return mService.getForceEphemeralUsers(admin);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return false;
@@ -3115,7 +3111,7 @@
try {
mService.setKeyguardDisabledFeatures(admin, which, mParentInstance);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -3144,7 +3140,7 @@
try {
return mService.getKeyguardDisabledFeatures(admin, userHandle, mParentInstance);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return KEYGUARD_DISABLE_FEATURES_NONE;
@@ -3159,7 +3155,7 @@
try {
mService.setActiveAdmin(policyReceiver, refreshing, userHandle);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -3179,7 +3175,7 @@
try {
mService.getRemoveWarning(admin, result, myUserId());
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -3194,7 +3190,7 @@
mService.setActivePasswordState(quality, length, letters, uppercase, lowercase,
numbers, symbols, nonletter, userHandle);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -3207,7 +3203,7 @@
try {
mService.reportFailedPasswordAttempt(userHandle);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -3220,7 +3216,7 @@
try {
mService.reportSuccessfulPasswordAttempt(userHandle);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -3233,7 +3229,7 @@
try {
mService.reportFailedFingerprintAttempt(userHandle);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -3246,7 +3242,7 @@
try {
mService.reportSuccessfulFingerprintAttempt(userHandle);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -3260,7 +3256,7 @@
try {
mService.reportKeyguardDismissed(userHandle);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -3274,7 +3270,7 @@
try {
mService.reportKeyguardSecured(userHandle);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -3327,7 +3323,7 @@
try {
return mService.setDeviceOwner(who, ownerName, userId);
} catch (RemoteException re) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
+ throw re.rethrowFromSystemServer();
}
}
return false;
@@ -3409,7 +3405,7 @@
try {
return mService.getDeviceOwnerComponent(callingUserOnly);
} catch (RemoteException re) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
+ throw re.rethrowFromSystemServer();
}
}
return null;
@@ -3428,7 +3424,7 @@
try {
return mService.getDeviceOwnerUserId();
} catch (RemoteException re) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
+ throw re.rethrowFromSystemServer();
}
}
return UserHandle.USER_NULL;
@@ -3448,7 +3444,7 @@
try {
mService.clearDeviceOwner(packageName);
} catch (RemoteException re) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
+ throw re.rethrowFromSystemServer();
}
}
}
@@ -3491,7 +3487,7 @@
try {
return mService.getDeviceOwnerName();
} catch (RemoteException re) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
+ throw re.rethrowFromSystemServer();
}
}
return null;
@@ -3544,7 +3540,7 @@
mService.setActiveAdmin(admin, false, myUserId);
return mService.setProfileOwner(admin, ownerName, myUserId);
} catch (RemoteException re) {
- throw new IllegalArgumentException("Couldn't set profile owner.", re);
+ throw re.rethrowFromSystemServer();
}
}
return false;
@@ -3564,7 +3560,7 @@
try {
mService.clearProfileOwner(admin);
} catch (RemoteException re) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
+ throw re.rethrowFromSystemServer();
}
}
}
@@ -3578,7 +3574,7 @@
try {
return mService.hasUserSetupCompleted();
} catch (RemoteException re) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
+ throw re.rethrowFromSystemServer();
}
}
return true;
@@ -3609,8 +3605,7 @@
}
return mService.setProfileOwner(admin, ownerName, userHandle);
} catch (RemoteException re) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
- throw new IllegalArgumentException("Couldn't set profile owner.", re);
+ throw re.rethrowFromSystemServer();
}
}
return false;
@@ -3638,7 +3633,7 @@
try {
return mService.setDeviceOwnerLockScreenInfo(admin, info);
} catch (RemoteException re) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
+ throw re.rethrowFromSystemServer();
}
}
return false;
@@ -3652,7 +3647,7 @@
try {
return mService.getDeviceOwnerLockScreenInfo();
} catch (RemoteException re) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
+ throw re.rethrowFromSystemServer();
}
}
return null;
@@ -3680,7 +3675,7 @@
try {
return mService.setPackagesSuspended(admin, packageNames, suspended);
} catch (RemoteException re) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
+ throw re.rethrowFromSystemServer();
}
}
return packageNames;
@@ -3699,7 +3694,7 @@
try {
return mService.getPackageSuspended(admin, packageName);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return false;
@@ -3718,7 +3713,7 @@
try {
mService.setProfileEnabled(admin);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -3739,7 +3734,7 @@
try {
mService.setProfileName(admin, profileName);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -3759,7 +3754,7 @@
return profileOwner != null
&& profileOwner.getPackageName().equals(packageName);
} catch (RemoteException re) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
+ throw re.rethrowFromSystemServer();
}
}
return false;
@@ -3785,9 +3780,7 @@
try {
return mService.getProfileOwner(userId);
} catch (RemoteException re) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
- throw new IllegalArgumentException(
- "Requested profile owner for invalid userId", re);
+ throw re.rethrowFromSystemServer();
}
}
return null;
@@ -3804,9 +3797,7 @@
try {
return mService.getProfileOwnerName(Process.myUserHandle().getIdentifier());
} catch (RemoteException re) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
- throw new IllegalArgumentException(
- "Requested profile owner for invalid userId", re);
+ throw re.rethrowFromSystemServer();
}
}
return null;
@@ -3825,9 +3816,7 @@
try {
return mService.getProfileOwnerName(userId);
} catch (RemoteException re) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
- throw new IllegalArgumentException(
- "Requested profile owner for invalid userId", re);
+ throw re.rethrowFromSystemServer();
}
}
return null;
@@ -3856,7 +3845,7 @@
try {
mService.addPersistentPreferredActivity(admin, filter, activity);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -3877,7 +3866,7 @@
try {
mService.clearPackagePersistentPreferredActivities(admin, packageName);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -3903,7 +3892,7 @@
try {
mService.setApplicationRestrictionsManagingPackage(admin, packageName);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -3921,7 +3910,7 @@
try {
return mService.getApplicationRestrictionsManagingPackage(admin);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return null;
@@ -3937,7 +3926,7 @@
try {
return mService.isCallerApplicationRestrictionsManagingPackage();
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return false;
@@ -3982,7 +3971,7 @@
try {
mService.setApplicationRestrictions(admin, packageName, settings);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -4012,7 +4001,7 @@
try {
mService.setTrustAgentConfiguration(admin, target, configuration);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -4043,7 +4032,7 @@
try {
return mService.getTrustAgentConfiguration(admin, agent, userHandle);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return new ArrayList<PersistableBundle>(); // empty list
@@ -4064,7 +4053,7 @@
try {
mService.setCrossProfileCallerIdDisabled(admin, disabled);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -4083,7 +4072,7 @@
try {
return mService.getCrossProfileCallerIdDisabled(admin);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return false;
@@ -4100,7 +4089,7 @@
try {
return mService.getCrossProfileCallerIdDisabledForUser(userHandle.getIdentifier());
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return false;
@@ -4122,7 +4111,7 @@
try {
mService.setCrossProfileContactsSearchDisabled(admin, disabled);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -4141,7 +4130,7 @@
try {
return mService.getCrossProfileContactsSearchDisabled(admin);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return false;
@@ -4160,7 +4149,7 @@
return mService
.getCrossProfileContactsSearchDisabledForUser(userHandle.getIdentifier());
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return false;
@@ -4178,7 +4167,7 @@
mService.startManagedQuickContact(actualLookupKey, actualContactId,
isContactIdIgnored, directoryId, originalIntent);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -4212,7 +4201,7 @@
try {
mService.setBluetoothContactSharingDisabled(admin, disabled);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -4234,7 +4223,7 @@
try {
return mService.getBluetoothContactSharingDisabled(admin);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return true;
@@ -4254,7 +4243,7 @@
return mService.getBluetoothContactSharingDisabledForUser(userHandle
.getIdentifier());
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return true;
@@ -4276,7 +4265,7 @@
try {
mService.addCrossProfileIntentFilter(admin, filter, flags);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -4292,7 +4281,7 @@
try {
mService.clearCrossProfileIntentFilters(admin);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -4324,7 +4313,7 @@
try {
return mService.setPermittedAccessibilityServices(admin, packageNames);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return false;
@@ -4344,7 +4333,7 @@
try {
return mService.getPermittedAccessibilityServices(admin);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return null;
@@ -4367,7 +4356,7 @@
return mService.isAccessibilityServicePermittedByAdmin(admin, packageName,
userHandle);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return false;
@@ -4391,7 +4380,7 @@
try {
return mService.getPermittedAccessibilityServicesForUser(userId);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return null;
@@ -4425,7 +4414,7 @@
try {
return mService.setPermittedInputMethods(admin, packageNames);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return false;
@@ -4446,7 +4435,7 @@
try {
return mService.getPermittedInputMethods(admin);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return null;
@@ -4468,7 +4457,7 @@
try {
return mService.isInputMethodPermittedByAdmin(admin, packageName, userHandle);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return false;
@@ -4491,7 +4480,7 @@
try {
return mService.getPermittedInputMethodsForCurrentUser();
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return null;
@@ -4511,7 +4500,7 @@
try {
return mService.getKeepUninstalledPackages(admin);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return null;
@@ -4534,7 +4523,7 @@
try {
mService.setKeepUninstalledPackages(admin, packageNames);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -4639,9 +4628,8 @@
try {
return mService.createAndManageUser(admin, name, profileOwner, adminExtras, flags);
} catch (RemoteException re) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
+ throw re.rethrowFromSystemServer();
}
- return null;
}
/**
@@ -4656,8 +4644,7 @@
try {
return mService.removeUser(admin, userHandle);
} catch (RemoteException re) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
- return false;
+ throw re.rethrowFromSystemServer();
}
}
@@ -4674,8 +4661,7 @@
try {
return mService.switchUser(admin, userHandle);
} catch (RemoteException re) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
- return false;
+ throw re.rethrowFromSystemServer();
}
}
@@ -4701,7 +4687,7 @@
try {
return mService.getApplicationRestrictions(admin, packageName);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return null;
@@ -4723,7 +4709,7 @@
try {
mService.setUserRestriction(admin, key, true);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -4744,7 +4730,7 @@
try {
mService.setUserRestriction(admin, key, false);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -4771,7 +4757,7 @@
try {
ret = mService.getUserRestrictions(admin, userHandle);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return ret == null ? new Bundle() : ret;
@@ -4793,7 +4779,7 @@
try {
return mService.setApplicationHidden(admin, packageName, hidden);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return false;
@@ -4811,7 +4797,7 @@
try {
return mService.isApplicationHidden(admin, packageName);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return false;
@@ -4829,7 +4815,7 @@
try {
mService.enableSystemApp(admin, packageName);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -4848,7 +4834,7 @@
try {
return mService.enableSystemAppWithIntent(admin, intent);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return 0;
@@ -4879,7 +4865,7 @@
try {
mService.setAccountManagementDisabled(admin, accountType, disabled);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -4907,7 +4893,7 @@
try {
return mService.getAccountTypesWithManagementDisabledAsUser(userId);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -4938,7 +4924,7 @@
try {
mService.setLockTaskPackages(admin, packages);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -4954,7 +4940,7 @@
try {
return mService.getLockTaskPackages(admin);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return null;
@@ -4970,7 +4956,7 @@
try {
return mService.isLockTaskPermitted(pkg);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return false;
@@ -5017,7 +5003,7 @@
try {
mService.setGlobalSetting(admin, setting, value);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -5045,7 +5031,7 @@
try {
mService.setSecureSetting(admin, setting, value);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -5066,7 +5052,7 @@
try {
mService.setRestrictionsProvider(admin, provider);
} catch (RemoteException re) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
+ throw re.rethrowFromSystemServer();
}
}
}
@@ -5082,7 +5068,7 @@
try {
mService.setMasterVolumeMuted(admin, on);
} catch (RemoteException re) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
+ throw re.rethrowFromSystemServer();
}
}
}
@@ -5098,7 +5084,7 @@
try {
return mService.isMasterVolumeMuted(admin);
} catch (RemoteException re) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
+ throw re.rethrowFromSystemServer();
}
}
return false;
@@ -5118,7 +5104,7 @@
try {
mService.setUninstallBlocked(admin, packageName, uninstallBlocked);
} catch (RemoteException re) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
+ throw re.rethrowFromSystemServer();
}
}
}
@@ -5142,7 +5128,7 @@
try {
return mService.isUninstallBlocked(admin, packageName);
} catch (RemoteException re) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
+ throw re.rethrowFromSystemServer();
}
}
return false;
@@ -5170,7 +5156,7 @@
try {
return mService.addCrossProfileWidgetProvider(admin, packageName);
} catch (RemoteException re) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
+ throw re.rethrowFromSystemServer();
}
}
return false;
@@ -5198,7 +5184,7 @@
try {
return mService.removeCrossProfileWidgetProvider(admin, packageName);
} catch (RemoteException re) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
+ throw re.rethrowFromSystemServer();
}
}
return false;
@@ -5222,7 +5208,7 @@
return providers;
}
} catch (RemoteException re) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
+ throw re.rethrowFromSystemServer();
}
}
return Collections.emptyList();
@@ -5238,7 +5224,7 @@
try {
mService.setUserIcon(admin, icon);
} catch (RemoteException re) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
+ throw re.rethrowFromSystemServer();
}
}
@@ -5258,7 +5244,7 @@
try {
mService.setSystemUpdatePolicy(admin, policy);
} catch (RemoteException re) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
+ throw re.rethrowFromSystemServer();
}
}
}
@@ -5273,7 +5259,7 @@
try {
return mService.getSystemUpdatePolicy();
} catch (RemoteException re) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
+ throw re.rethrowFromSystemServer();
}
}
return null;
@@ -5297,8 +5283,7 @@
try {
return mService.setKeyguardDisabled(admin, disabled);
} catch (RemoteException re) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
- return false;
+ throw re.rethrowFromSystemServer();
}
}
@@ -5317,8 +5302,7 @@
try {
return mService.setStatusBarDisabled(admin, disabled);
} catch (RemoteException re) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
- return false;
+ throw re.rethrowFromSystemServer();
}
}
@@ -5337,7 +5321,7 @@
try {
mService.notifyPendingSystemUpdate(updateReceivedTime);
} catch (RemoteException re) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
+ throw re.rethrowFromSystemServer();
}
}
}
@@ -5363,7 +5347,7 @@
try {
mService.setPermissionPolicy(admin, policy);
} catch (RemoteException re) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
+ throw re.rethrowFromSystemServer();
}
}
@@ -5377,7 +5361,7 @@
try {
return mService.getPermissionPolicy(admin);
} catch (RemoteException re) {
- return PERMISSION_POLICY_PROMPT;
+ throw re.rethrowFromSystemServer();
}
}
@@ -5414,8 +5398,7 @@
try {
return mService.setPermissionGrantState(admin, packageName, permission, grantState);
} catch (RemoteException re) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
- return false;
+ throw re.rethrowFromSystemServer();
}
}
@@ -5441,8 +5424,7 @@
try {
return mService.getPermissionGrantState(admin, packageName, permission);
} catch (RemoteException re) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
- return PERMISSION_GRANT_STATE_DEFAULT;
+ throw re.rethrowFromSystemServer();
}
}
@@ -5460,8 +5442,7 @@
try {
return mService.isProvisioningAllowed(action);
} catch (RemoteException re) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
- return false;
+ throw re.rethrowFromSystemServer();
}
}
@@ -5477,8 +5458,7 @@
try {
return mService.isManagedProfile(admin);
} catch (RemoteException re) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
- return false;
+ throw re.rethrowFromSystemServer();
}
}
@@ -5493,8 +5473,7 @@
try {
return mService.isSystemOnlyUser(admin);
} catch (RemoteException re) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
- return false;
+ throw re.rethrowFromSystemServer();
}
}
@@ -5510,8 +5489,7 @@
try {
return mService.getWifiMacAddress();
} catch (RemoteException re) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
- return null;
+ throw re.rethrowFromSystemServer();
}
}
@@ -5522,7 +5500,7 @@
try {
mService.reboot(admin);
} catch (RemoteException re) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
+ throw re.rethrowFromSystemServer();
}
}
@@ -5552,7 +5530,7 @@
try {
mService.setShortSupportMessage(admin, message);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -5569,7 +5547,7 @@
try {
return mService.getShortSupportMessage(admin);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return null;
@@ -5595,7 +5573,7 @@
try {
mService.setLongSupportMessage(admin, message);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -5612,7 +5590,7 @@
try {
return mService.getLongSupportMessage(admin);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return null;
@@ -5632,7 +5610,7 @@
try {
return mService.getShortSupportMessageForUser(admin, userHandle);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return null;
@@ -5653,7 +5631,7 @@
try {
return mService.getLongSupportMessageForUser(admin, userHandle);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return null;
@@ -5674,8 +5652,7 @@
}
return new DevicePolicyManager(mContext, true);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
- return null;
+ throw e.rethrowFromSystemServer();
}
}
@@ -5697,7 +5674,7 @@
try {
mService.setDeviceLoggingEnabled(admin, enabled);
} catch (RemoteException re) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
+ throw re.rethrowFromSystemServer();
}
}
@@ -5714,8 +5691,7 @@
try {
return mService.getDeviceLoggingEnabled(admin);
} catch (RemoteException re) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
- return false;
+ throw re.rethrowFromSystemServer();
}
}
@@ -5743,8 +5719,7 @@
return null;
}
} catch (RemoteException re) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
- return null;
+ throw re.rethrowFromSystemServer();
}
}
@@ -5784,8 +5759,7 @@
ParceledListSlice<SecurityEvent> list = mService.retrievePreviousDeviceLogs(admin);
return list.getList();
} catch (RemoteException re) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
- return Collections.<SecurityEvent>emptyList();
+ throw re.rethrowFromSystemServer();
}
}
@@ -5804,7 +5778,7 @@
try {
mService.setOrganizationColor(admin, color);
} catch (RemoteException re) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
+ throw re.rethrowFromSystemServer();
}
}
@@ -5823,7 +5797,7 @@
try {
mService.setOrganizationColorForUser(color, userId);
} catch (RemoteException re) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
+ throw re.rethrowFromSystemServer();
}
}
@@ -5838,8 +5812,7 @@
try {
return mService.getOrganizationColor(admin);
} catch (RemoteException re) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
- return 0;
+ throw re.rethrowFromSystemServer();
}
}
@@ -5854,8 +5827,7 @@
try {
return mService.getOrganizationColorForUser(userHandle);
} catch (RemoteException re) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
- return 0;
+ throw re.rethrowFromSystemServer();
}
}
@@ -5874,7 +5846,7 @@
try {
mService.setOrganizationName(admin, title);
} catch (RemoteException re) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE);
+ throw re.rethrowFromSystemServer();
}
}
@@ -5889,8 +5861,7 @@
try {
return mService.getOrganizationName(admin);
} catch (RemoteException re) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE);
- return null;
+ throw re.rethrowFromSystemServer();
}
}
@@ -5906,8 +5877,7 @@
try {
return mService.getOrganizationNameForUser(userHandle);
} catch (RemoteException re) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE);
- return null;
+ throw re.rethrowFromSystemServer();
}
}
@@ -5923,7 +5893,7 @@
try {
return mService.getUserProvisioningState();
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
return STATE_USER_UNMANAGED;
@@ -5941,7 +5911,7 @@
try {
mService.setUserProvisioningState(state, userHandle);
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -5968,7 +5938,7 @@
try {
mService.setAffiliationIds(admin, new ArrayList<String>(ids));
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -5983,8 +5953,7 @@
try {
return mService != null && mService.isAffiliatedUser();
} catch (RemoteException e) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, e);
- return false;
+ throw e.rethrowFromSystemServer();
}
}
@@ -5999,8 +5968,7 @@
try {
return mService.isUninstallInQueue(packageName);
} catch (RemoteException re) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
- return false;
+ throw re.rethrowFromSystemServer();
}
}
@@ -6012,7 +5980,7 @@
try {
mService.uninstallPackageWithActiveAdmins(packageName);
} catch (RemoteException re) {
- Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
+ throw re.rethrowFromSystemServer();
}
}
}
diff --git a/core/java/android/bluetooth/OobData.java b/core/java/android/bluetooth/OobData.java
index 7194938..70d47ee 100644
--- a/core/java/android/bluetooth/OobData.java
+++ b/core/java/android/bluetooth/OobData.java
@@ -25,7 +25,7 @@
* Out Of Band Data for Bluetooth device.
* @hide
*/
-public final class OobData implements Parcelable {
+public class OobData implements Parcelable {
private byte[] securityManagerTk;
public byte[] getSecurityManagerTk() {
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index 9959f27..0389085 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -530,4 +530,7 @@
String getServicesSystemSharedLibraryPackageName();
boolean isPackageDeviceAdminOnAnyUser(String packageName);
+
+ List<String> getPreviousCodePaths(in String packageName);
+
}
diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java
index 2cbb782..700a40d 100644
--- a/core/java/android/content/pm/PackageInstaller.java
+++ b/core/java/android/content/pm/PackageInstaller.java
@@ -1042,6 +1042,11 @@
}
/** {@hide} */
+ public void setInstallFlagsDontKillApp() {
+ installFlags |= PackageManager.INSTALL_DONT_KILL_APP;
+ }
+
+ /** {@hide} */
public void dump(IndentingPrintWriter pw) {
pw.printPair("mode", mode);
pw.printHexPair("installFlags", installFlags);
diff --git a/core/java/android/content/pm/PackageItemInfo.java b/core/java/android/content/pm/PackageItemInfo.java
index 4df83036..edd888b 100644
--- a/core/java/android/content/pm/PackageItemInfo.java
+++ b/core/java/android/content/pm/PackageItemInfo.java
@@ -16,12 +16,16 @@
package android.content.pm;
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
import android.content.res.XmlResourceParser;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.Parcel;
import android.os.UserHandle;
+import android.text.BidiFormatter;
+import android.text.TextPaint;
import android.text.TextUtils;
import android.util.Printer;
@@ -38,6 +42,8 @@
* in the implementation of Parcelable in subclasses.
*/
public class PackageItemInfo {
+ private static final float MAX_LABEL_SIZE_PX = 500f;
+
/**
* Public name of this item. From the "android:name" attribute.
*/
@@ -140,6 +146,56 @@
}
/**
+ * Same as {@link #loadLabel(PackageManager)} with the addition that
+ * the returned label is safe for being presented in the UI since it
+ * will not contain new lines and the length will be limited to a
+ * reasonable amount. This prevents a malicious party to influence UI
+ * layout via the app label misleading the user into performing a
+ * detrimental for them action. If the label is too long it will be
+ * truncated and ellipsized at the end.
+ *
+ * @param pm A PackageManager from which the label can be loaded; usually
+ * the PackageManager from which you originally retrieved this item
+ * @return Returns a CharSequence containing the item's label. If the
+ * item does not have a label, its name is returned.
+ *
+ * @hide
+ */
+ @SystemApi
+ public @NonNull CharSequence loadSafeLabel(@NonNull PackageManager pm) {
+ // loadLabel() always returns non-null
+ CharSequence label = loadLabel(pm);
+
+ // If the label contains new line characters it may push the UI
+ // down to hide a part of it. Labels shouldn't have new line
+ // characters, so just truncate at the first time one is seen.
+ String labelStr = label.toString();
+ final int labelLength = labelStr.length();
+ int offset = 0;
+ while (offset < labelLength) {
+ final int codePoint = labelStr.codePointAt(offset);
+ final int type = Character.getType(codePoint);
+ if (type == Character.LINE_SEPARATOR
+ || type == Character.CONTROL
+ || type == Character.PARAGRAPH_SEPARATOR) {
+ labelStr = labelStr.substring(0, offset);
+ break;
+ }
+ offset += Character.charCount(codePoint);
+ }
+
+ if (labelStr.isEmpty()) {
+ return labelStr;
+ }
+
+ TextPaint paint = new TextPaint();
+ paint.setTextSize(42);
+
+ return TextUtils.ellipsize(labelStr, paint, MAX_LABEL_SIZE_PX,
+ TextUtils.TruncateAt.END);
+ }
+
+ /**
* Retrieve the current graphical icon associated with this item. This
* will call back on the given PackageManager to load the icon from
* the application.
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index c2d1bdd..0dc856c 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -538,6 +538,7 @@
INSTALL_FORCE_VOLUME_UUID,
INSTALL_FORCE_PERMISSION_PROMPT,
INSTALL_EPHEMERAL,
+ INSTALL_DONT_KILL_APP,
})
@Retention(RetentionPolicy.SOURCE)
public @interface InstallFlags {}
@@ -640,6 +641,15 @@
public static final int INSTALL_EPHEMERAL = 0x00000800;
/**
+ * Flag parameter for {@link #installPackage} to indicate that this package contains
+ * a feature split to an existing application and the existing application should not
+ * be killed during the installation process.
+ *
+ * @hide
+ */
+ public static final int INSTALL_DONT_KILL_APP = 0x00001000;
+
+ /**
* Flag parameter for
* {@link #setComponentEnabledSetting(android.content.ComponentName, int, int)} to indicate
* that you don't want to kill the app containing the component. Be careful when you set this
@@ -1088,6 +1098,7 @@
DELETE_KEEP_DATA,
DELETE_ALL_USERS,
DELETE_SYSTEM_APP,
+ DELETE_DONT_KILL_APP,
})
@Retention(RetentionPolicy.SOURCE)
public @interface DeleteFlags {}
@@ -1120,6 +1131,15 @@
public static final int DELETE_SYSTEM_APP = 0x00000004;
/**
+ * Flag parameter for {@link #deletePackage} to indicate that, if you are calling
+ * uninstall on a package that is replaced to provide new feature splits, the
+ * existing application should not be killed during the removal process.
+ *
+ * @hide
+ */
+ public static final int DELETE_DONT_KILL_APP = 0x00000008;
+
+ /**
* Return code for when package deletion succeeds. This is passed to the
* {@link IPackageDeleteObserver} if the system succeeded in deleting the
* package.
@@ -1292,6 +1312,7 @@
*
* @hide
*/
+ @SystemApi
public static final int INTENT_FILTER_VERIFICATION_SUCCESS = 1;
/**
@@ -1301,6 +1322,7 @@
*
* @hide
*/
+ @SystemApi
public static final int INTENT_FILTER_VERIFICATION_FAILURE = -1;
/**
@@ -4339,6 +4361,32 @@
throws NameNotFoundException;
/**
+ * Returns a managed-user-style badged copy of the given drawable allowing the user to
+ * distinguish it from the original drawable.
+ * The caller can specify the location in the bounds of the drawable to be
+ * badged where the badge should be applied as well as the density of the
+ * badge to be used.
+ * <p>
+ * If the original drawable is a BitmapDrawable and the backing bitmap is
+ * mutable as per {@link android.graphics.Bitmap#isMutable()}, the badging
+ * is performed in place and the original drawable is returned.
+ * </p>
+ *
+ * @param drawable The drawable to badge.
+ * @param badgeLocation Where in the bounds of the badged drawable to place
+ * the badge. If it's {@code null}, the badge is applied on top of the entire
+ * drawable being badged.
+ * @param badgeDensity The optional desired density for the badge as per
+ * {@link android.util.DisplayMetrics#densityDpi}. If it's not positive,
+ * the density of the display is used.
+ * @return A drawable that combines the original drawable and a badge as
+ * determined by the system.
+ * @hide
+ */
+ public abstract Drawable getManagedUserBadgedDrawable(Drawable drawable, Rect badgeLocation,
+ int badgeDensity);
+
+ /**
* If the target user is a managed profile of the calling user or if the
* target user is the caller and is itself a managed profile, then this
* returns a badged copy of the given icon to be able to distinguish it from
@@ -4367,17 +4415,17 @@
* badge to be used.
* <p>
* If the original drawable is a BitmapDrawable and the backing bitmap is
- * mutable as per {@link android.graphics.Bitmap#isMutable()}, the bading
+ * mutable as per {@link android.graphics.Bitmap#isMutable()}, the badging
* is performed in place and the original drawable is returned.
* </p>
*
* @param drawable The drawable to badge.
* @param user The target user.
* @param badgeLocation Where in the bounds of the badged drawable to place
- * the badge. If not provided, the badge is applied on top of the entire
+ * the badge. If it's {@code null}, the badge is applied on top of the entire
* drawable being badged.
* @param badgeDensity The optional desired density for the badge as per
- * {@link android.util.DisplayMetrics#densityDpi}. If not provided,
+ * {@link android.util.DisplayMetrics#densityDpi}. If it's not positive,
* the density of the display is used.
* @return A drawable that combines the original drawable and a badge as
* determined by the system.
@@ -4685,8 +4733,8 @@
/**
* Allows a package listening to the
- * {@link Intent#ACTION_INTENT_FILTER_NEEDS_VERIFICATION intent filter verification
- * broadcast} to respond to the package manager. The response must include
+ * {@link Intent#ACTION_INTENT_FILTER_NEEDS_VERIFICATION} intent filter verification
+ * broadcast to respond to the package manager. The response must include
* the {@code verificationCode} which is one of
* {@link PackageManager#INTENT_FILTER_VERIFICATION_SUCCESS} or
* {@link PackageManager#INTENT_FILTER_VERIFICATION_FAILURE}.
@@ -4695,7 +4743,7 @@
* {@link PackageManager#EXTRA_VERIFICATION_ID} Intent extra.
* @param verificationCode either {@link PackageManager#INTENT_FILTER_VERIFICATION_SUCCESS}
* or {@link PackageManager#INTENT_FILTER_VERIFICATION_FAILURE}.
- * @param outFailedDomains a list of failed domains if the verificationCode is
+ * @param failedDomains a list of failed domains if the verificationCode is
* {@link PackageManager#INTENT_FILTER_VERIFICATION_FAILURE}, otherwise null;
* @throws SecurityException if the caller does not have the
* INTENT_FILTER_VERIFICATION_AGENT permission.
@@ -4704,7 +4752,7 @@
*/
@SystemApi
public abstract void verifyIntentFilter(int verificationId, int verificationCode,
- List<String> outFailedDomains);
+ List<String> failedDomains);
/**
* Get the status of a Domain Verification Result for an IntentFilter. This is
diff --git a/core/java/android/content/pm/PackageManagerInternal.java b/core/java/android/content/pm/PackageManagerInternal.java
index 7fe7f84..89f2fc4 100644
--- a/core/java/android/content/pm/PackageManagerInternal.java
+++ b/core/java/android/content/pm/PackageManagerInternal.java
@@ -16,6 +16,8 @@
package android.content.pm;
+import android.content.pm.PackageManager.NameNotFoundException;
+
import java.util.List;
/**
@@ -125,4 +127,17 @@
* @return True a permissions review is required.
*/
public abstract boolean isPermissionsReviewRequired(String packageName, int userId);
+
+ /**
+ * Gets all of the information we know about a particular package.
+ *
+ * @param packageName The package name to find.
+ * @param userId The user under which to check.
+ *
+ * @return An {@link ApplicationInfo} containing information about the
+ * package.
+ * @throws NameNotFoundException if a package with the given name cannot be
+ * found on the system.
+ */
+ public abstract ApplicationInfo getApplicationInfo(String packageName, int userId);
}
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index ce6ddfd..0588a9d 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -4690,9 +4690,6 @@
// preferred up order.
public int mPreferredOrder = 0;
- // For use by package manager to keep track of where it needs to do dexopt.
- public final ArraySet<String> mDexOptPerformed = new ArraySet<>(4);
-
// For use by package manager to keep track of when a package was last used.
public long mLastPackageUsageTimeInMills;
diff --git a/core/java/android/content/res/ConfigurationBoundResourceCache.java b/core/java/android/content/res/ConfigurationBoundResourceCache.java
index fecda87..40d2a82 100644
--- a/core/java/android/content/res/ConfigurationBoundResourceCache.java
+++ b/core/java/android/content/res/ConfigurationBoundResourceCache.java
@@ -23,29 +23,19 @@
* @hide For internal use only.
*/
public class ConfigurationBoundResourceCache<T> extends ThemedResourceCache<ConstantState<T>> {
- private final Resources mResources;
-
- /**
- * Creates a cache for the given Resources instance.
- *
- * @param resources the resources to use when creating new instances
- */
- public ConfigurationBoundResourceCache(Resources resources) {
- mResources = resources;
- }
-
/**
* If the resource is cached, creates and returns a new instance of it.
*
* @param key a key that uniquely identifies the drawable resource
+ * @param resources a Resources object from which to create new instances.
* @param theme the theme where the resource will be used
* @return a new instance of the resource, or {@code null} if not in
* the cache
*/
- public T getInstance(long key, Resources.Theme theme) {
+ public T getInstance(long key, Resources resources, Resources.Theme theme) {
final ConstantState<T> entry = get(key, theme);
if (entry != null) {
- return entry.newInstance(mResources, theme);
+ return entry.newInstance(resources, theme);
}
return null;
diff --git a/core/java/android/content/res/DrawableCache.java b/core/java/android/content/res/DrawableCache.java
index ba00134..7b27fac 100644
--- a/core/java/android/content/res/DrawableCache.java
+++ b/core/java/android/content/res/DrawableCache.java
@@ -22,29 +22,19 @@
* Class which can be used to cache Drawable resources against a theme.
*/
class DrawableCache extends ThemedResourceCache<Drawable.ConstantState> {
- private final Resources mResources;
-
- /**
- * Creates a cache for the given Resources instance.
- *
- * @param resources the resources to use when creating new instances
- */
- public DrawableCache(Resources resources) {
- mResources = resources;
- }
-
/**
* If the resource is cached, creates and returns a new instance of it.
*
* @param key a key that uniquely identifies the drawable resource
+ * @param resources a Resources object from which to create new instances.
* @param theme the theme where the resource will be used
* @return a new instance of the resource, or {@code null} if not in
* the cache
*/
- public Drawable getInstance(long key, Resources.Theme theme) {
+ public Drawable getInstance(long key, Resources resources, Resources.Theme theme) {
final Drawable.ConstantState entry = get(key, theme);
if (entry != null) {
- return entry.newDrawable(mResources, theme);
+ return entry.newDrawable(resources, theme);
}
return null;
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index a54f40f..f337fe6 100644
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -40,23 +40,17 @@
import android.annotation.XmlRes;
import android.content.pm.ActivityInfo;
import android.graphics.Movie;
-import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.Drawable.ConstantState;
import android.graphics.drawable.DrawableInflater;
-import android.icu.text.PluralRules;
import android.os.Build;
import android.os.Bundle;
-import android.os.Trace;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
-import android.util.LocaleList;
import android.util.Log;
import android.util.LongSparseArray;
import android.util.Pools.SynchronizedPool;
-import android.util.Slog;
import android.util.TypedValue;
-import android.util.Xml;
import android.view.ViewDebug;
import android.view.ViewHierarchyEncoder;
@@ -68,8 +62,6 @@
import java.io.IOException;
import java.io.InputStream;
-import java.util.Arrays;
-import java.util.Locale;
/**
* Class for accessing an application's resources. This sits on top of the
@@ -99,51 +91,15 @@
public class Resources {
static final String TAG = "Resources";
- private static final boolean DEBUG_LOAD = false;
- private static final boolean DEBUG_CONFIG = false;
- private static final boolean TRACE_FOR_PRELOAD = false;
- private static final boolean TRACE_FOR_MISS_PRELOAD = false;
-
- private static final int LAYOUT_DIR_CONFIG = ActivityInfo.activityInfoConfigToNative(
- ActivityInfo.CONFIG_LAYOUT_DIRECTION);
-
- private static final int ID_OTHER = 0x01000004;
-
private static final Object sSync = new Object();
- // Information about preloaded resources. Note that they are not
- // protected by a lock, because while preloading in zygote we are all
- // single-threaded, and after that these are immutable.
- private static final LongSparseArray<ConstantState>[] sPreloadedDrawables;
- private static final LongSparseArray<ConstantState> sPreloadedColorDrawables
- = new LongSparseArray<>();
- private static final LongSparseArray<android.content.res.ConstantState<ComplexColor>>
- sPreloadedComplexColors = new LongSparseArray<>();
-
- /** Size of the cyclical cache used to map XML files to blocks. */
- private static final int XML_BLOCK_CACHE_SIZE = 4;
-
- // Pool of TypedArrays targeted to this Resources object.
- final SynchronizedPool<TypedArray> mTypedArrayPool = new SynchronizedPool<>(5);
-
// Used by BridgeResources in layoutlib
static Resources mSystem = null;
- private static boolean sPreloaded;
+ private ResourcesImpl mResourcesImpl;
- /** Lock object used to protect access to caches and configuration. */
- private final Object mAccessLock = new Object();
-
- // These are protected by mAccessLock.
- private final Configuration mTmpConfig = new Configuration();
- private final DrawableCache mDrawableCache = new DrawableCache(this);
- private final DrawableCache mColorDrawableCache = new DrawableCache(this);
- private final ConfigurationBoundResourceCache<ComplexColor> mComplexColorCache =
- new ConfigurationBoundResourceCache<>(this);
- private final ConfigurationBoundResourceCache<Animator> mAnimatorCache =
- new ConfigurationBoundResourceCache<>(this);
- private final ConfigurationBoundResourceCache<StateListAnimator> mStateListAnimatorCache =
- new ConfigurationBoundResourceCache<>(this);
+ // Pool of TypedArrays targeted to this Resources object.
+ final SynchronizedPool<TypedArray> mTypedArrayPool = new SynchronizedPool<>(5);
/** Used to inflate drawable objects from XML. */
private DrawableInflater mDrawableInflater;
@@ -154,29 +110,7 @@
/** Single-item pool used to minimize TypedValue allocations. */
private TypedValue mTmpValue = new TypedValue();
- private boolean mPreloading;
-
- // Cyclical cache used for recently-accessed XML files.
- private int mLastCachedXmlBlockIndex = -1;
- private final int[] mCachedXmlBlockCookies = new int[XML_BLOCK_CACHE_SIZE];
- private final String[] mCachedXmlBlockFiles = new String[XML_BLOCK_CACHE_SIZE];
- private final XmlBlock[] mCachedXmlBlocks = new XmlBlock[XML_BLOCK_CACHE_SIZE];
-
- final AssetManager mAssets;
final ClassLoader mClassLoader;
- final DisplayMetrics mMetrics = new DisplayMetrics();
-
- private final Configuration mConfiguration = new Configuration();
-
- private PluralRules mPluralRule;
-
- private CompatibilityInfo mCompatibilityInfo = CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO;
-
- static {
- sPreloadedDrawables = new LongSparseArray[2];
- sPreloadedDrawables[0] = new LongSparseArray<>();
- sPreloadedDrawables[1] = new LongSparseArray<>();
- }
/**
* Returns the most appropriate default theme for the specified target SDK version.
@@ -219,32 +153,20 @@
}
/**
- * @return the inflater used to create drawable objects
- * @hide Pending API finalization.
+ * Return a global shared Resources object that provides access to only
+ * system resources (no application resources), and is not configured for
+ * the current screen (can not use dimension units, does not change based
+ * on orientation, etc).
*/
- public final DrawableInflater getDrawableInflater() {
- if (mDrawableInflater == null) {
- mDrawableInflater = new DrawableInflater(this, mClassLoader);
+ public static Resources getSystem() {
+ synchronized (sSync) {
+ Resources ret = mSystem;
+ if (ret == null) {
+ ret = new Resources();
+ mSystem = ret;
+ }
+ return ret;
}
- return mDrawableInflater;
- }
-
- /**
- * Used by AnimatorInflater.
- *
- * @hide
- */
- public ConfigurationBoundResourceCache<Animator> getAnimatorCache() {
- return mAnimatorCache;
- }
-
- /**
- * Used by AnimatorInflater.
- *
- * @hide
- */
- public ConfigurationBoundResourceCache<StateListAnimator> getStateListAnimatorCache() {
- return mStateListAnimatorCache;
}
/**
@@ -275,51 +197,73 @@
* selecting/computing resource values (optional).
*/
public Resources(AssetManager assets, DisplayMetrics metrics, Configuration config) {
- this(assets, metrics, config, CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null);
+ this(null);
+ mResourcesImpl = new ResourcesImpl(assets, metrics, config,
+ CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO);
}
/**
* Creates a new Resources object with CompatibilityInfo.
*
- * @param assets Previously created AssetManager.
- * @param metrics Current display metrics to consider when
- * selecting/computing resource values.
- * @param config Desired device configuration to consider when
- * selecting/computing resource values (optional).
- * @param compatInfo this resource's compatibility info. Must not be null.
* @param classLoader class loader for the package used to load custom
* resource classes, may be {@code null} to use system
* class loader
* @hide
*/
- public Resources(AssetManager assets, DisplayMetrics metrics, Configuration config,
- CompatibilityInfo compatInfo, @Nullable ClassLoader classLoader) {
- mAssets = assets;
+ public Resources(@Nullable ClassLoader classLoader) {
mClassLoader = classLoader == null ? ClassLoader.getSystemClassLoader() : classLoader;
- mMetrics.setToDefaults();
- if (compatInfo != null) {
- mCompatibilityInfo = compatInfo;
- }
- updateConfiguration(config, metrics);
- assets.ensureStringBlocks();
}
/**
- * Return a global shared Resources object that provides access to only
- * system resources (no application resources), and is not configured for
- * the current screen (can not use dimension units, does not change based
- * on orientation, etc).
+ * Only for creating the System resources.
*/
- public static Resources getSystem() {
- synchronized (sSync) {
- Resources ret = mSystem;
- if (ret == null) {
- ret = new Resources();
- mSystem = ret;
- }
+ private Resources() {
+ this(null);
- return ret;
+ final DisplayMetrics metrics = new DisplayMetrics();
+ metrics.setToDefaults();
+
+ final Configuration config = new Configuration();
+ config.setToDefaults();
+
+ mResourcesImpl = new ResourcesImpl(AssetManager.getSystem(), metrics, config,
+ CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO);
+ }
+
+ /**
+ * @hide
+ */
+ public void setImpl(ResourcesImpl impl) {
+ mResourcesImpl = impl;
+ }
+
+ /**
+ * @return the inflater used to create drawable objects
+ * @hide Pending API finalization.
+ */
+ public final DrawableInflater getDrawableInflater() {
+ if (mDrawableInflater == null) {
+ mDrawableInflater = new DrawableInflater(this, mClassLoader);
}
+ return mDrawableInflater;
+ }
+
+ /**
+ * Used by AnimatorInflater.
+ *
+ * @hide
+ */
+ public ConfigurationBoundResourceCache<Animator> getAnimatorCache() {
+ return mResourcesImpl.getAnimatorCache();
+ }
+
+ /**
+ * Used by AnimatorInflater.
+ *
+ * @hide
+ */
+ public ConfigurationBoundResourceCache<StateListAnimator> getStateListAnimatorCache() {
+ return mResourcesImpl.getStateListAnimatorCache();
}
/**
@@ -337,8 +281,8 @@
* @return CharSequence The string data associated with the resource, plus
* possibly styled text information.
*/
- public CharSequence getText(@StringRes int id) throws NotFoundException {
- CharSequence res = mAssets.getResourceText(id);
+ @NonNull public CharSequence getText(@StringRes int id) throws NotFoundException {
+ CharSequence res = mResourcesImpl.getAssets().getResourceText(id);
if (res != null) {
return res;
}
@@ -366,41 +310,10 @@
* @return CharSequence The string data associated with the resource, plus
* possibly styled text information.
*/
+ @NonNull
public CharSequence getQuantityText(@PluralsRes int id, int quantity)
throws NotFoundException {
- PluralRules rule = getPluralRule();
- CharSequence res = mAssets.getResourceBagText(id,
- attrForQuantityCode(rule.select(quantity)));
- if (res != null) {
- return res;
- }
- res = mAssets.getResourceBagText(id, ID_OTHER);
- if (res != null) {
- return res;
- }
- throw new NotFoundException("Plural resource ID #0x" + Integer.toHexString(id)
- + " quantity=" + quantity
- + " item=" + rule.select(quantity));
- }
-
- private PluralRules getPluralRule() {
- synchronized (sSync) {
- if (mPluralRule == null) {
- mPluralRule = PluralRules.forLocale(mConfiguration.getLocales().get(0));
- }
- return mPluralRule;
- }
- }
-
- private static int attrForQuantityCode(String quantityCode) {
- switch (quantityCode) {
- case PluralRules.KEYWORD_ZERO: return 0x01000005;
- case PluralRules.KEYWORD_ONE: return 0x01000006;
- case PluralRules.KEYWORD_TWO: return 0x01000007;
- case PluralRules.KEYWORD_FEW: return 0x01000008;
- case PluralRules.KEYWORD_MANY: return 0x01000009;
- default: return ID_OTHER;
- }
+ return mResourcesImpl.getQuantityText(id, quantity);
}
/**
@@ -419,12 +332,7 @@
*/
@NonNull
public String getString(@StringRes int id) throws NotFoundException {
- final CharSequence res = getText(id);
- if (res != null) {
- return res.toString();
- }
- throw new NotFoundException("String resource ID #0x"
- + Integer.toHexString(id));
+ return getText(id).toString();
}
@@ -449,7 +357,8 @@
@NonNull
public String getString(@StringRes int id, Object... formatArgs) throws NotFoundException {
final String raw = getString(id);
- return String.format(mConfiguration.getLocales().get(0), raw, formatArgs);
+ return String.format(mResourcesImpl.getConfiguration().getLocales().get(0), raw,
+ formatArgs);
}
/**
@@ -477,10 +386,12 @@
* @return String The string data associated with the resource,
* stripped of styled text information.
*/
+ @NonNull
public String getQuantityString(@PluralsRes int id, int quantity, Object... formatArgs)
throws NotFoundException {
String raw = getQuantityText(id, quantity).toString();
- return String.format(mConfiguration.getLocales().get(0), raw, formatArgs);
+ return String.format(mResourcesImpl.getConfiguration().getLocales().get(0), raw,
+ formatArgs);
}
/**
@@ -503,8 +414,8 @@
* @return String The string data associated with the resource,
* stripped of styled text information.
*/
- public String getQuantityString(@PluralsRes int id, int quantity)
- throws NotFoundException {
+ @NonNull
+ public String getQuantityString(@PluralsRes int id, int quantity) throws NotFoundException {
return getQuantityText(id, quantity).toString();
}
@@ -523,7 +434,7 @@
* possibly styled text information, or def if id is 0 or not found.
*/
public CharSequence getText(@StringRes int id, CharSequence def) {
- CharSequence res = id != 0 ? mAssets.getResourceText(id) : null;
+ CharSequence res = id != 0 ? mResourcesImpl.getAssets().getResourceText(id) : null;
return res != null ? res : def;
}
@@ -538,13 +449,13 @@
*
* @return The styled text array associated with the resource.
*/
+ @NonNull
public CharSequence[] getTextArray(@ArrayRes int id) throws NotFoundException {
- CharSequence[] res = mAssets.getResourceTextArray(id);
+ CharSequence[] res = mResourcesImpl.getAssets().getResourceTextArray(id);
if (res != null) {
return res;
}
- throw new NotFoundException("Text array resource ID #0x"
- + Integer.toHexString(id));
+ throw new NotFoundException("Text array resource ID #0x" + Integer.toHexString(id));
}
/**
@@ -558,14 +469,14 @@
*
* @return The string array associated with the resource.
*/
+ @NonNull
public String[] getStringArray(@ArrayRes int id)
throws NotFoundException {
- String[] res = mAssets.getResourceStringArray(id);
+ String[] res = mResourcesImpl.getAssets().getResourceStringArray(id);
if (res != null) {
return res;
}
- throw new NotFoundException("String array resource ID #0x"
- + Integer.toHexString(id));
+ throw new NotFoundException("String array resource ID #0x" + Integer.toHexString(id));
}
/**
@@ -579,13 +490,13 @@
*
* @return The int array associated with the resource.
*/
+ @NonNull
public int[] getIntArray(@ArrayRes int id) throws NotFoundException {
- int[] res = mAssets.getArrayIntResource(id);
+ int[] res = mResourcesImpl.getAssets().getArrayIntResource(id);
if (res != null) {
return res;
}
- throw new NotFoundException("Int array resource ID #0x"
- + Integer.toHexString(id));
+ throw new NotFoundException("Int array resource ID #0x" + Integer.toHexString(id));
}
/**
@@ -601,16 +512,16 @@
* Be sure to call {@link TypedArray#recycle() TypedArray.recycle()}
* when done with it.
*/
- public TypedArray obtainTypedArray(@ArrayRes int id)
- throws NotFoundException {
- int len = mAssets.getArraySize(id);
+ @NonNull
+ public TypedArray obtainTypedArray(@ArrayRes int id) throws NotFoundException {
+ final ResourcesImpl impl = mResourcesImpl;
+ int len = impl.getAssets().getArraySize(id);
if (len < 0) {
- throw new NotFoundException("Array resource ID #0x"
- + Integer.toHexString(id));
+ throw new NotFoundException("Array resource ID #0x" + Integer.toHexString(id));
}
TypedArray array = TypedArray.obtain(this, len);
- array.mLength = mAssets.retrieveArray(id, array.mData);
+ array.mLength = impl.getAssets().retrieveArray(id, array.mData);
array.mIndices[0] = 0;
return array;
@@ -634,10 +545,12 @@
* @see #getDimensionPixelSize
*/
public float getDimension(@DimenRes int id) throws NotFoundException {
- final TypedValue value = obtainTempTypedValue(id);
+ final TypedValue value = obtainTempTypedValue();
try {
+ final ResourcesImpl impl = mResourcesImpl;
+ impl.getValue(id, value, true);
if (value.type == TypedValue.TYPE_DIMENSION) {
- return TypedValue.complexToDimension(value.data, mMetrics);
+ return TypedValue.complexToDimension(value.data, impl.getDisplayMetrics());
}
throw new NotFoundException("Resource ID #0x" + Integer.toHexString(id)
+ " type #0x" + Integer.toHexString(value.type) + " is not valid");
@@ -666,10 +579,13 @@
* @see #getDimensionPixelSize
*/
public int getDimensionPixelOffset(@DimenRes int id) throws NotFoundException {
- final TypedValue value = obtainTempTypedValue(id);
+ final TypedValue value = obtainTempTypedValue();
try {
+ final ResourcesImpl impl = mResourcesImpl;
+ impl.getValue(id, value, true);
if (value.type == TypedValue.TYPE_DIMENSION) {
- return TypedValue.complexToDimensionPixelOffset(value.data, mMetrics);
+ return TypedValue.complexToDimensionPixelOffset(value.data,
+ impl.getDisplayMetrics());
}
throw new NotFoundException("Resource ID #0x" + Integer.toHexString(id)
+ " type #0x" + Integer.toHexString(value.type) + " is not valid");
@@ -699,10 +615,12 @@
* @see #getDimensionPixelOffset
*/
public int getDimensionPixelSize(@DimenRes int id) throws NotFoundException {
- final TypedValue value = obtainTempTypedValue(id);
+ final TypedValue value = obtainTempTypedValue();
try {
+ final ResourcesImpl impl = mResourcesImpl;
+ impl.getValue(id, value, true);
if (value.type == TypedValue.TYPE_DIMENSION) {
- return TypedValue.complexToDimensionPixelSize(value.data, mMetrics);
+ return TypedValue.complexToDimensionPixelSize(value.data, impl.getDisplayMetrics());
}
throw new NotFoundException("Resource ID #0x" + Integer.toHexString(id)
+ " type #0x" + Integer.toHexString(value.type) + " is not valid");
@@ -729,8 +647,9 @@
* @throws NotFoundException Throws NotFoundException if the given ID does not exist.
*/
public float getFraction(@FractionRes int id, int base, int pbase) {
- final TypedValue value = obtainTempTypedValue(id);
+ final TypedValue value = obtainTempTypedValue();
try {
+ mResourcesImpl.getValue(id, value, true);
if (value.type == TypedValue.TYPE_FRACTION) {
return TypedValue.complexToFraction(value.data, base, pbase);
}
@@ -800,9 +719,11 @@
*/
public Drawable getDrawable(@DrawableRes int id, @Nullable Theme theme)
throws NotFoundException {
- final TypedValue value = obtainTempTypedValue(id);
+ final TypedValue value = obtainTempTypedValue();
try {
- return loadDrawable(value, id, theme);
+ final ResourcesImpl impl = mResourcesImpl;
+ impl.getValue(id, value, true);
+ return impl.loadDrawable(this, value, id, theme, true);
} finally {
releaseTempTypedValue(value);
}
@@ -855,14 +776,16 @@
* not exist.
*/
public Drawable getDrawableForDensity(@DrawableRes int id, int density, @Nullable Theme theme) {
- final TypedValue value = obtainTempTypedValue(id);
+ final TypedValue value = obtainTempTypedValue();
try {
- getValueForDensity(id, density, value, true);
+ final ResourcesImpl impl = mResourcesImpl;
+ impl.getValueForDensity(id, density, value, true);
// If the drawable's XML lives in our current density qualifier,
// it's okay to use a scaled version from the cache. Otherwise, we
// need to actually load the drawable from XML.
- final boolean useCache = value.density == mMetrics.densityDpi;
+ final DisplayMetrics metrics = impl.getDisplayMetrics();
+ final boolean useCache = value.density == metrics.densityDpi;
/*
* Pretend the requested density is actually the display density. If
@@ -873,18 +796,23 @@
*/
if (value.density > 0 && value.density != TypedValue.DENSITY_NONE) {
if (value.density == density) {
- value.density = mMetrics.densityDpi;
+ value.density = metrics.densityDpi;
} else {
- value.density = (value.density * mMetrics.densityDpi) / density;
+ value.density = (value.density * metrics.densityDpi) / density;
}
}
-
- return loadDrawable(value, id, theme, useCache);
+ return impl.loadDrawable(this, value, id, theme, useCache);
} finally {
releaseTempTypedValue(value);
}
}
+ @NonNull
+ Drawable loadDrawable(@NonNull TypedValue value, int id, @Nullable Theme theme)
+ throws NotFoundException {
+ return mResourcesImpl.loadDrawable(this, value, id, theme, true);
+ }
+
/**
* Return a movie object associated with the particular resource ID.
* @param id The desired resource identifier, as generated by the aapt
@@ -894,13 +822,12 @@
*
*/
public Movie getMovie(@RawRes int id) throws NotFoundException {
- InputStream is = openRawResource(id);
- Movie movie = Movie.decodeStream(is);
+ final InputStream is = openRawResource(id);
+ final Movie movie = Movie.decodeStream(is);
try {
is.close();
- }
- catch (java.io.IOException e) {
- // don't care, since the return value is valid
+ } catch (IOException e) {
+ // No one cares.
}
return movie;
}
@@ -944,8 +871,10 @@
*/
@ColorInt
public int getColor(@ColorRes int id, @Nullable Theme theme) throws NotFoundException {
- final TypedValue value = obtainTempTypedValue(id);
+ final TypedValue value = obtainTempTypedValue();
try {
+ final ResourcesImpl impl = mResourcesImpl;
+ impl.getValue(id, value, true);
if (value.type >= TypedValue.TYPE_FIRST_INT
&& value.type <= TypedValue.TYPE_LAST_INT) {
return value.data;
@@ -954,7 +883,7 @@
+ " type #0x" + Integer.toHexString(value.type) + " is not valid");
}
- final ColorStateList csl = loadColorStateList(value, id, theme);
+ final ColorStateList csl = impl.loadColorStateList(this, value, id, theme);
return csl.getDefaultColor();
} finally {
releaseTempTypedValue(value);
@@ -1012,14 +941,27 @@
@Nullable
public ColorStateList getColorStateList(@ColorRes int id, @Nullable Theme theme)
throws NotFoundException {
- final TypedValue value = obtainTempTypedValue(id);
+ final TypedValue value = obtainTempTypedValue();
try {
- return loadColorStateList(value, id, theme);
+ final ResourcesImpl impl = mResourcesImpl;
+ impl.getValue(id, value, true);
+ return impl.loadColorStateList(this, value, id, theme);
} finally {
releaseTempTypedValue(value);
}
}
+ @Nullable
+ ColorStateList loadColorStateList(@NonNull TypedValue value, int id, @Nullable Theme theme)
+ throws NotFoundException {
+ return mResourcesImpl.loadColorStateList(this, value, id, theme);
+ }
+
+ @Nullable
+ public ComplexColor loadComplexColor(@NonNull TypedValue value, int id, @Nullable Theme theme) {
+ return mResourcesImpl.loadComplexColor(this, value, id, theme);
+ }
+
/**
* Return a boolean associated with a particular resource ID. This can be
* used with any integral resource value, and will return true if it is
@@ -1034,8 +976,9 @@
* @return Returns the boolean value contained in the resource.
*/
public boolean getBoolean(@BoolRes int id) throws NotFoundException {
- final TypedValue value = obtainTempTypedValue(id);
+ final TypedValue value = obtainTempTypedValue();
try {
+ mResourcesImpl.getValue(id, value, true);
if (value.type >= TypedValue.TYPE_FIRST_INT
&& value.type <= TypedValue.TYPE_LAST_INT) {
return value.data != 0;
@@ -1059,8 +1002,9 @@
* @return Returns the integer value contained in the resource.
*/
public int getInteger(@IntegerRes int id) throws NotFoundException {
- final TypedValue value = obtainTempTypedValue(id);
+ final TypedValue value = obtainTempTypedValue();
try {
+ mResourcesImpl.getValue(id, value, true);
if (value.type >= TypedValue.TYPE_FIRST_INT
&& value.type <= TypedValue.TYPE_LAST_INT) {
return value.data;
@@ -1086,8 +1030,9 @@
* @hide Pending API council approval.
*/
public float getFloat(int id) {
- final TypedValue value = obtainTempTypedValue(id);
+ final TypedValue value = obtainTempTypedValue();
try {
+ mResourcesImpl.getValue(id, value, true);
if (value.type == TypedValue.TYPE_FLOAT) {
return value.getFloat();
}
@@ -1195,20 +1140,6 @@
}
/**
- * Returns a TypedValue populated with data for the specified resource ID
- * that's suitable for temporary use. The obtained TypedValue should be
- * released using {@link #releaseTempTypedValue(TypedValue)}.
- *
- * @param id the resource ID for which data should be obtained
- * @return a populated typed value suitable for temporary use
- */
- private TypedValue obtainTempTypedValue(@AnyRes int id) {
- final TypedValue value = obtainTempTypedValue();
- getValue(id, value, true);
- return value;
- }
-
- /**
* Returns a TypedValue suitable for temporary use. The obtained TypedValue
* should be released using {@link #releaseTempTypedValue(TypedValue)}.
*
@@ -1257,17 +1188,7 @@
*/
public InputStream openRawResource(@RawRes int id, TypedValue value)
throws NotFoundException {
- getValue(id, value, true);
-
- try {
- return mAssets.openNonAsset(value.assetCookie, value.string.toString(),
- AssetManager.ACCESS_STREAMING);
- } catch (Exception e) {
- NotFoundException rnf = new NotFoundException("File " + value.string.toString() +
- " from drawable resource ID #0x" + Integer.toHexString(id));
- rnf.initCause(e);
- throw rnf;
- }
+ return mResourcesImpl.openRawResource(id, value);
}
/**
@@ -1293,12 +1214,9 @@
*/
public AssetFileDescriptor openRawResourceFd(@RawRes int id)
throws NotFoundException {
- final TypedValue value = obtainTempTypedValue(id);
+ final TypedValue value = obtainTempTypedValue();
try {
- return mAssets.openNonAssetFd(value.assetCookie, value.string.toString());
- } catch (Exception e) {
- throw new NotFoundException("File " + value.string.toString() + " from drawable "
- + "resource ID #0x" + Integer.toHexString(id), e);
+ return mResourcesImpl.openRawResourceFd(id, value);
} finally {
releaseTempTypedValue(value);
}
@@ -1321,12 +1239,7 @@
*/
public void getValue(@AnyRes int id, TypedValue outValue, boolean resolveRefs)
throws NotFoundException {
- boolean found = mAssets.getResourceValue(id, 0, outValue, resolveRefs);
- if (found) {
- return;
- }
- throw new NotFoundException("Resource ID #0x"
- + Integer.toHexString(id));
+ mResourcesImpl.getValue(id, outValue, resolveRefs);
}
/**
@@ -1344,11 +1257,7 @@
*/
public void getValueForDensity(@AnyRes int id, int density, TypedValue outValue,
boolean resolveRefs) throws NotFoundException {
- boolean found = mAssets.getResourceValue(id, density, outValue, resolveRefs);
- if (found) {
- return;
- }
- throw new NotFoundException("Resource ID #0x" + Integer.toHexString(id));
+ mResourcesImpl.getValueForDensity(id, density, outValue, resolveRefs);
}
/**
@@ -1373,12 +1282,7 @@
*/
public void getValue(String name, TypedValue outValue, boolean resolveRefs)
throws NotFoundException {
- int id = getIdentifier(name, "string", null);
- if (id != 0) {
- getValue(id, outValue, resolveRefs);
- return;
- }
- throw new NotFoundException("String resource name " + name);
+ mResourcesImpl.getValue(name, outValue, resolveRefs);
}
/**
@@ -1397,6 +1301,15 @@
* retrieve XML attributes with style and theme information applied.
*/
public final class Theme {
+ private ResourcesImpl.ThemeImpl mThemeImpl;
+
+ private Theme() {
+ }
+
+ void setImpl(ResourcesImpl.ThemeImpl impl) {
+ mThemeImpl = impl;
+ }
+
/**
* Place new attribute values into the theme. The style resource
* specified by <var>resid</var> will be retrieved from this Theme's
@@ -1415,12 +1328,7 @@
* if not already defined in the theme.
*/
public void applyStyle(int resId, boolean force) {
- synchronized (mKey) {
- AssetManager.applyThemeStyle(mTheme, resId, force);
-
- mThemeResId = resId;
- mKey.append(resId, force);
- }
+ mThemeImpl.applyStyle(resId, force);
}
/**
@@ -1433,14 +1341,7 @@
* @param other The existing Theme to copy from.
*/
public void setTo(Theme other) {
- synchronized (mKey) {
- synchronized (other.mKey) {
- AssetManager.copyTheme(mTheme, other.mTheme);
-
- mThemeResId = other.mThemeResId;
- mKey.setTo(other.getKey());
- }
- }
+ mThemeImpl.setTo(other.mThemeImpl);
}
/**
@@ -1463,13 +1364,7 @@
* @see #obtainStyledAttributes(AttributeSet, int[], int, int)
*/
public TypedArray obtainStyledAttributes(@StyleableRes int[] attrs) {
- synchronized (mKey) {
- final int len = attrs.length;
- final TypedArray array = TypedArray.obtain(Resources.this, len);
- array.mTheme = this;
- AssetManager.applyStyle(mTheme, 0, 0, 0, attrs, array.mData, array.mIndices);
- return array;
- }
+ return mThemeImpl.obtainStyledAttributes(this, null, attrs, 0, 0);
}
/**
@@ -1494,13 +1389,7 @@
*/
public TypedArray obtainStyledAttributes(@StyleRes int resId, @StyleableRes int[] attrs)
throws NotFoundException {
- synchronized (mKey) {
- final int len = attrs.length;
- final TypedArray array = TypedArray.obtain(Resources.this, len);
- array.mTheme = this;
- AssetManager.applyStyle(mTheme, 0, resId, 0, attrs, array.mData, array.mIndices);
- return array;
- }
+ return mThemeImpl.obtainStyledAttributes(this, null, attrs, 0, resId);
}
/**
@@ -1553,23 +1442,7 @@
*/
public TypedArray obtainStyledAttributes(AttributeSet set,
@StyleableRes int[] attrs, @AttrRes int defStyleAttr, @StyleRes int defStyleRes) {
- synchronized (mKey) {
- final int len = attrs.length;
- final TypedArray array = TypedArray.obtain(Resources.this, len);
-
- // XXX note that for now we only work with compiled XML files.
- // To support generic XML files we will need to manually parse
- // out the attributes from the XML file (applying type information
- // contained in the resources and such).
- final XmlBlock.Parser parser = (XmlBlock.Parser) set;
- AssetManager.applyStyle(mTheme, defStyleAttr, defStyleRes,
- parser != null ? parser.mParseState : 0,
- attrs, array.mData, array.mIndices);
- array.mTheme = this;
- array.mXml = parser;
-
- return array;
- }
+ return mThemeImpl.obtainStyledAttributes(this, set, attrs, defStyleAttr, defStyleRes);
}
/**
@@ -1588,20 +1461,7 @@
*/
@NonNull
public TypedArray resolveAttributes(@NonNull int[] values, @NonNull int[] attrs) {
- synchronized (mKey) {
- final int len = attrs.length;
- if (values == null || len != values.length) {
- throw new IllegalArgumentException(
- "Base attribute values must the same length as attrs");
- }
-
- final TypedArray array = TypedArray.obtain(Resources.this, len);
- AssetManager.resolveAttrs(mTheme, 0, 0, values, attrs, array.mData, array.mIndices);
- array.mTheme = this;
- array.mXml = null;
-
- return array;
- }
+ return mThemeImpl.resolveAttributes(this, values, attrs);
}
/**
@@ -1622,9 +1482,7 @@
* <var>outValue</var> is valid, else false.
*/
public boolean resolveAttribute(int resid, TypedValue outValue, boolean resolveRefs) {
- synchronized (mKey) {
- return mAssets.getThemeValue(mTheme, resid, outValue, resolveRefs);
- }
+ return mThemeImpl.resolveAttribute(resid, outValue, resolveRefs);
}
/**
@@ -1634,7 +1492,7 @@
* @hide
*/
public int[] getAllAttributes() {
- return mAssets.getStyleAttributes(getAppliedStyleResId());
+ return mThemeImpl.getAllAttributes();
}
/**
@@ -1670,11 +1528,7 @@
* @see ActivityInfo
*/
public int getChangingConfigurations() {
- synchronized (mKey) {
- final int nativeChangingConfig =
- AssetManager.getThemeChangingConfigurations(mTheme);
- return ActivityInfo.activityInfoConfigNativeToJava(nativeChangingConfig);
- }
+ return mThemeImpl.getChangingConfigurations();
}
/**
@@ -1685,43 +1539,23 @@
* @param prefix Text to prefix each line printed.
*/
public void dump(int priority, String tag, String prefix) {
- synchronized (mKey) {
- AssetManager.dumpTheme(mTheme, priority, tag, prefix);
- }
+ mThemeImpl.dump(priority, tag, prefix);
}
- @Override
- protected void finalize() throws Throwable {
- super.finalize();
- mAssets.releaseTheme(mTheme);
- }
-
- /*package*/ Theme() {
- mAssets = Resources.this.mAssets;
- mTheme = mAssets.createTheme();
- }
-
- /** Unique key for the series of styles applied to this theme. */
- private final ThemeKey mKey = new ThemeKey();
-
- @SuppressWarnings("hiding")
- private final AssetManager mAssets;
- private final long mTheme;
-
- /** Resource identifier for the theme. */
- private int mThemeResId = 0;
-
// Needed by layoutlib.
/*package*/ long getNativeTheme() {
- return mTheme;
+ return mThemeImpl.getNativeTheme();
}
/*package*/ int getAppliedStyleResId() {
- return mThemeResId;
+ return mThemeImpl.getAppliedStyleResId();
}
- /*package*/ ThemeKey getKey() {
- return mKey;
+ /**
+ * @hide
+ */
+ public ThemeKey getKey() {
+ return mThemeImpl.getKey();
}
private String getResourceNameFromHexString(String hexString) {
@@ -1729,7 +1563,7 @@
}
/**
- * Parses {@link #mKey} and returns a String array that holds pairs of
+ * Parses {@link #getKey()} and returns a String array that holds pairs of
* adjacent Theme data: resource name followed by whether or not it was
* forced, as specified by {@link #applyStyle(int, boolean)}.
*
@@ -1737,21 +1571,7 @@
*/
@ViewDebug.ExportedProperty(category = "theme", hasAdjacentMapping = true)
public String[] getTheme() {
- synchronized (mKey) {
- final int N = mKey.mCount;
- final String[] themes = new String[N * 2];
- for (int i = 0, j = N - 1; i < themes.length; i += 2, --j) {
- final int resId = mKey.mResId[j];
- final boolean forced = mKey.mForce[j];
- try {
- themes[i] = getResourceName(resId);
- } catch (NotFoundException e) {
- themes[i] = Integer.toHexString(i);
- }
- themes[i + 1] = forced ? "forced" : "not forced";
- }
- return themes;
- }
+ return mThemeImpl.getTheme();
}
/** @hide */
@@ -1772,16 +1592,7 @@
* @hide
*/
public void rebase() {
- synchronized (mKey) {
- AssetManager.clearTheme(mTheme);
-
- // Reapply the same styles in the same order.
- for (int i = 0; i < mKey.mCount; i++) {
- final int resId = mKey.mResId[i];
- final boolean force = mKey.mForce[i];
- AssetManager.applyThemeStyle(mTheme, resId, force);
- }
- }
+ mThemeImpl.rebase();
}
}
@@ -1870,7 +1681,9 @@
* @return Theme The newly created Theme container.
*/
public final Theme newTheme() {
- return new Theme();
+ Theme theme = new Theme();
+ theme.setImpl(mResourcesImpl.newThemeImpl());
+ return theme;
}
/**
@@ -1894,7 +1707,7 @@
// out the attributes from the XML file (applying type information
// contained in the resources and such).
XmlBlock.Parser parser = (XmlBlock.Parser)set;
- mAssets.retrieveAttributes(parser.mParseState, attrs,
+ mResourcesImpl.getAssets().retrieveAttributes(parser.mParseState, attrs,
array.mData, array.mIndices);
array.mXml = parser;
@@ -1905,151 +1718,16 @@
/**
* Store the newly updated configuration.
*/
- public void updateConfiguration(Configuration config,
- DisplayMetrics metrics) {
+ public void updateConfiguration(Configuration config, DisplayMetrics metrics) {
updateConfiguration(config, metrics, null);
}
/**
* @hide
*/
- public void updateConfiguration(Configuration config,
- DisplayMetrics metrics, CompatibilityInfo compat) {
- synchronized (mAccessLock) {
- if (false) {
- Slog.i(TAG, "**** Updating config of " + this + ": old config is "
- + mConfiguration + " old compat is " + mCompatibilityInfo);
- Slog.i(TAG, "**** Updating config of " + this + ": new config is "
- + config + " new compat is " + compat);
- }
- if (compat != null) {
- mCompatibilityInfo = compat;
- }
- if (metrics != null) {
- mMetrics.setTo(metrics);
- }
- // NOTE: We should re-arrange this code to create a Display
- // with the CompatibilityInfo that is used everywhere we deal
- // with the display in relation to this app, rather than
- // doing the conversion here. This impl should be okay because
- // we make sure to return a compatible display in the places
- // where there are public APIs to retrieve the display... but
- // it would be cleaner and more maintainble to just be
- // consistently dealing with a compatible display everywhere in
- // the framework.
- mCompatibilityInfo.applyToDisplayMetrics(mMetrics);
-
- final int configChanges = calcConfigChanges(config);
-
- LocaleList locales = mConfiguration.getLocales();
- if (locales.isEmpty()) {
- locales = LocaleList.getAdjustedDefault();
- mConfiguration.setLocales(locales);
- }
- if (mConfiguration.densityDpi != Configuration.DENSITY_DPI_UNDEFINED) {
- mMetrics.densityDpi = mConfiguration.densityDpi;
- mMetrics.density = mConfiguration.densityDpi * DisplayMetrics.DENSITY_DEFAULT_SCALE;
- }
- mMetrics.scaledDensity = mMetrics.density * mConfiguration.fontScale;
-
- final int width, height;
- if (mMetrics.widthPixels >= mMetrics.heightPixels) {
- width = mMetrics.widthPixels;
- height = mMetrics.heightPixels;
- } else {
- //noinspection SuspiciousNameCombination
- width = mMetrics.heightPixels;
- //noinspection SuspiciousNameCombination
- height = mMetrics.widthPixels;
- }
-
- final int keyboardHidden;
- if (mConfiguration.keyboardHidden == Configuration.KEYBOARDHIDDEN_NO
- && mConfiguration.hardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_YES) {
- keyboardHidden = Configuration.KEYBOARDHIDDEN_SOFT;
- } else {
- keyboardHidden = mConfiguration.keyboardHidden;
- }
-
- mAssets.setConfiguration(mConfiguration.mcc, mConfiguration.mnc,
- adjustLanguageTag(locales.get(0).toLanguageTag()),
- mConfiguration.orientation,
- mConfiguration.touchscreen,
- mConfiguration.densityDpi, mConfiguration.keyboard,
- keyboardHidden, mConfiguration.navigation, width, height,
- mConfiguration.smallestScreenWidthDp,
- mConfiguration.screenWidthDp, mConfiguration.screenHeightDp,
- mConfiguration.screenLayout, mConfiguration.uiMode,
- Build.VERSION.RESOURCES_SDK_INT);
-
- if (DEBUG_CONFIG) {
- Slog.i(TAG, "**** Updating config of " + this + ": final config is "
- + mConfiguration + " final compat is " + mCompatibilityInfo);
- }
-
- mDrawableCache.onConfigurationChange(configChanges);
- mColorDrawableCache.onConfigurationChange(configChanges);
- mComplexColorCache.onConfigurationChange(configChanges);
- mAnimatorCache.onConfigurationChange(configChanges);
- mStateListAnimatorCache.onConfigurationChange(configChanges);
-
- flushLayoutCache();
- }
- synchronized (sSync) {
- if (mPluralRule != null) {
- mPluralRule = PluralRules.forLocale(mConfiguration.getLocales().get(0));
- }
- }
- }
-
- /**
- * Called by ConfigurationBoundResourceCacheTest via reflection.
- */
- private int calcConfigChanges(Configuration config) {
- int configChanges = 0xfffffff;
- if (config != null) {
- mTmpConfig.setTo(config);
- int density = config.densityDpi;
- if (density == Configuration.DENSITY_DPI_UNDEFINED) {
- density = mMetrics.noncompatDensityDpi;
- }
-
- mCompatibilityInfo.applyToConfiguration(density, mTmpConfig);
-
- if (mTmpConfig.getLocales().isEmpty()) {
- mTmpConfig.setLocales(LocaleList.getDefault());
- }
- configChanges = mConfiguration.updateFrom(mTmpConfig);
- configChanges = ActivityInfo.activityInfoConfigToNative(configChanges);
- }
- return configChanges;
- }
-
- /**
- * {@code Locale.toLanguageTag} will transform the obsolete (and deprecated)
- * language codes "in", "ji" and "iw" to "id", "yi" and "he" respectively.
- *
- * All released versions of android prior to "L" used the deprecated language
- * tags, so we will need to support them for backwards compatibility.
- *
- * Note that this conversion needs to take place *after* the call to
- * {@code toLanguageTag} because that will convert all the deprecated codes to
- * the new ones, even if they're set manually.
- */
- private static String adjustLanguageTag(String languageTag) {
- final int separator = languageTag.indexOf('-');
- final String language;
- final String remainder;
-
- if (separator == -1) {
- language = languageTag;
- remainder = "";
- } else {
- language = languageTag.substring(0, separator);
- remainder = languageTag.substring(separator);
- }
-
- return Locale.adjustLanguageCode(language) + remainder;
+ public void updateConfiguration(Configuration config, DisplayMetrics metrics,
+ CompatibilityInfo compat) {
+ mResourcesImpl.updateConfiguration(config, metrics, compat);
}
/**
@@ -2074,9 +1752,7 @@
* @return The resource's current display metrics.
*/
public DisplayMetrics getDisplayMetrics() {
- if (DEBUG_CONFIG) Slog.v(TAG, "Returning DisplayMetrics: " + mMetrics.widthPixels
- + "x" + mMetrics.heightPixels + " " + mMetrics.density);
- return mMetrics;
+ return mResourcesImpl.getDisplayMetrics();
}
/**
@@ -2086,13 +1762,13 @@
* @return The resource's current configuration.
*/
public Configuration getConfiguration() {
- return mConfiguration;
+ return mResourcesImpl.getConfiguration();
}
/** @hide */
public Configuration[] getSizeConfigurations() {
- return mAssets.getSizeConfigurations();
- };
+ return mResourcesImpl.getSizeConfigurations();
+ }
/**
* Return the compatibility mode information for the application.
@@ -2102,7 +1778,7 @@
* @hide
*/
public CompatibilityInfo getCompatibilityInfo() {
- return mCompatibilityInfo;
+ return mResourcesImpl.getCompatibilityInfo();
}
/**
@@ -2111,8 +1787,7 @@
*/
public void setCompatibilityInfo(CompatibilityInfo ci) {
if (ci != null) {
- mCompatibilityInfo = ci;
- updateConfiguration(mConfiguration, mMetrics);
+ mResourcesImpl.updateConfiguration(null, null, ci);
}
}
@@ -2137,15 +1812,7 @@
* resource was found. (0 is not a valid resource ID.)
*/
public int getIdentifier(String name, String defType, String defPackage) {
- if (name == null) {
- throw new NullPointerException("name is null");
- }
- try {
- return Integer.parseInt(name);
- } catch (Exception e) {
- // Ignore
- }
- return mAssets.getResourceIdentifier(name, defType, defPackage);
+ return mResourcesImpl.getIdentifier(name, defType, defPackage);
}
/**
@@ -2172,10 +1839,7 @@
* @see #getResourceEntryName
*/
public String getResourceName(@AnyRes int resid) throws NotFoundException {
- String str = mAssets.getResourceName(resid);
- if (str != null) return str;
- throw new NotFoundException("Unable to find resource ID #0x"
- + Integer.toHexString(resid));
+ return mResourcesImpl.getResourceName(resid);
}
/**
@@ -2191,10 +1855,7 @@
* @see #getResourceName
*/
public String getResourcePackageName(@AnyRes int resid) throws NotFoundException {
- String str = mAssets.getResourcePackageName(resid);
- if (str != null) return str;
- throw new NotFoundException("Unable to find resource ID #0x"
- + Integer.toHexString(resid));
+ return mResourcesImpl.getResourcePackageName(resid);
}
/**
@@ -2210,10 +1871,7 @@
* @see #getResourceName
*/
public String getResourceTypeName(@AnyRes int resid) throws NotFoundException {
- String str = mAssets.getResourceTypeName(resid);
- if (str != null) return str;
- throw new NotFoundException("Unable to find resource ID #0x"
- + Integer.toHexString(resid));
+ return mResourcesImpl.getResourceTypeName(resid);
}
/**
@@ -2229,10 +1887,7 @@
* @see #getResourceName
*/
public String getResourceEntryName(@AnyRes int resid) throws NotFoundException {
- String str = mAssets.getResourceEntryName(resid);
- if (str != null) return str;
- throw new NotFoundException("Unable to find resource ID #0x"
- + Integer.toHexString(resid));
+ return mResourcesImpl.getResourceEntryName(resid);
}
/**
@@ -2335,7 +1990,7 @@
* Retrieve underlying AssetManager storage for these resources.
*/
public final AssetManager getAssets() {
- return mAssets;
+ return mResourcesImpl.getAssets();
}
/**
@@ -2344,19 +1999,7 @@
* tools.
*/
public final void flushLayoutCache() {
- synchronized (mCachedXmlBlocks) {
- Arrays.fill(mCachedXmlBlockCookies, 0);
- Arrays.fill(mCachedXmlBlockFiles, null);
-
- final XmlBlock[] cachedXmlBlocks = mCachedXmlBlocks;
- for (int i = 0; i < XML_BLOCK_CACHE_SIZE; i++) {
- final XmlBlock oldBlock = cachedXmlBlocks[i];
- if (oldBlock != null) {
- oldBlock.close();
- }
- }
- Arrays.fill(cachedXmlBlocks, null);
- }
+ mResourcesImpl.flushLayoutCache();
}
/**
@@ -2365,15 +2008,7 @@
* {@hide}
*/
public final void startPreloading() {
- synchronized (sSync) {
- if (sPreloaded) {
- throw new IllegalStateException("Resources already preloaded");
- }
- sPreloaded = true;
- mPreloading = true;
- mConfiguration.densityDpi = DisplayMetrics.DENSITY_DEVICE;
- updateConfiguration(null, null);
- }
+ mResourcesImpl.startPreloading();
}
/**
@@ -2381,441 +2016,14 @@
* to normal Resources operation.
*/
public final void finishPreloading() {
- if (mPreloading) {
- mPreloading = false;
- flushLayoutCache();
- }
+ mResourcesImpl.finishPreloading();
}
/**
* @hide
*/
public LongSparseArray<ConstantState> getPreloadedDrawables() {
- return sPreloadedDrawables[0];
- }
-
- private boolean verifyPreloadConfig(int changingConfigurations, int allowVarying,
- int resourceId, String name) {
- // We allow preloading of resources even if they vary by font scale (which
- // doesn't impact resource selection) or density (which we handle specially by
- // simply turning off all preloading), as well as any other configs specified
- // by the caller.
- if (((changingConfigurations&~(ActivityInfo.CONFIG_FONT_SCALE |
- ActivityInfo.CONFIG_DENSITY)) & ~allowVarying) != 0) {
- String resName;
- try {
- resName = getResourceName(resourceId);
- } catch (NotFoundException e) {
- resName = "?";
- }
- // This should never happen in production, so we should log a
- // warning even if we're not debugging.
- Log.w(TAG, "Preloaded " + name + " resource #0x"
- + Integer.toHexString(resourceId)
- + " (" + resName + ") that varies with configuration!!");
- return false;
- }
- if (TRACE_FOR_PRELOAD) {
- String resName;
- try {
- resName = getResourceName(resourceId);
- } catch (NotFoundException e) {
- resName = "?";
- }
- Log.w(TAG, "Preloading " + name + " resource #0x"
- + Integer.toHexString(resourceId)
- + " (" + resName + ")");
- }
- return true;
- }
-
- @Nullable
- Drawable loadDrawable(TypedValue value, int id, Theme theme) throws NotFoundException {
- return loadDrawable(value, id, theme, true);
- }
-
- @Nullable
- Drawable loadDrawable(TypedValue value, int id, Theme theme, boolean useCache)
- throws NotFoundException {
- try {
- if (TRACE_FOR_PRELOAD) {
- // Log only framework resources
- if ((id >>> 24) == 0x1) {
- final String name = getResourceName(id);
- if (name != null) {
- Log.d("PreloadDrawable", name);
- }
- }
- }
-
- final boolean isColorDrawable;
- final DrawableCache caches;
- final long key;
- if (value.type >= TypedValue.TYPE_FIRST_COLOR_INT
- && value.type <= TypedValue.TYPE_LAST_COLOR_INT) {
- isColorDrawable = true;
- caches = mColorDrawableCache;
- key = value.data;
- } else {
- isColorDrawable = false;
- caches = mDrawableCache;
- key = (((long) value.assetCookie) << 32) | value.data;
- }
-
- // First, check whether we have a cached version of this drawable
- // that was inflated against the specified theme. Skip the cache if
- // we're currently preloading or we're not using the cache.
- if (!mPreloading && useCache) {
- final Drawable cachedDrawable = caches.getInstance(key, theme);
- if (cachedDrawable != null) {
- return cachedDrawable;
- }
- }
-
- // Next, check preloaded drawables. Preloaded drawables may contain
- // unresolved theme attributes.
- final ConstantState cs;
- if (isColorDrawable) {
- cs = sPreloadedColorDrawables.get(key);
- } else {
- cs = sPreloadedDrawables[mConfiguration.getLayoutDirection()].get(key);
- }
-
- Drawable dr;
- if (cs != null) {
- dr = cs.newDrawable(this);
- } else if (isColorDrawable) {
- dr = new ColorDrawable(value.data);
- } else {
- dr = loadDrawableForCookie(value, id, null);
- }
-
- // Determine if the drawable has unresolved theme attributes. If it
- // does, we'll need to apply a theme and store it in a theme-specific
- // cache.
- final boolean canApplyTheme = dr != null && dr.canApplyTheme();
- if (canApplyTheme && theme != null) {
- dr = dr.mutate();
- dr.applyTheme(theme);
- dr.clearMutated();
- }
-
- // If we were able to obtain a drawable, store it in the appropriate
- // cache: preload, not themed, null theme, or theme-specific. Don't
- // pollute the cache with drawables loaded from a foreign density.
- if (dr != null && useCache) {
- dr.setChangingConfigurations(value.changingConfigurations);
- cacheDrawable(value, isColorDrawable, caches, theme, canApplyTheme, key, dr);
- }
-
- return dr;
- } catch (Exception e) {
- String name;
- try {
- name = getResourceName(id);
- } catch (NotFoundException e2) {
- name = "(missing name)";
- }
-
- // The target drawable might fail to load for any number of
- // reasons, but we always want to include the resource name.
- // Since the client already expects this method to throw a
- // NotFoundException, just throw one of those.
- final NotFoundException nfe = new NotFoundException("Drawable " + name
- + " with resource ID #0x" + Integer.toHexString(id), e);
- nfe.setStackTrace(new StackTraceElement[0]);
- throw nfe;
- }
- }
-
- private void cacheDrawable(TypedValue value, boolean isColorDrawable, DrawableCache caches,
- Theme theme, boolean usesTheme, long key, Drawable dr) {
- final ConstantState cs = dr.getConstantState();
- if (cs == null) {
- return;
- }
-
- if (mPreloading) {
- final int changingConfigs = cs.getChangingConfigurations();
- if (isColorDrawable) {
- if (verifyPreloadConfig(changingConfigs, 0, value.resourceId, "drawable")) {
- sPreloadedColorDrawables.put(key, cs);
- }
- } else {
- if (verifyPreloadConfig(
- changingConfigs, LAYOUT_DIR_CONFIG, value.resourceId, "drawable")) {
- if ((changingConfigs & LAYOUT_DIR_CONFIG) == 0) {
- // If this resource does not vary based on layout direction,
- // we can put it in all of the preload maps.
- sPreloadedDrawables[0].put(key, cs);
- sPreloadedDrawables[1].put(key, cs);
- } else {
- // Otherwise, only in the layout dir we loaded it for.
- sPreloadedDrawables[mConfiguration.getLayoutDirection()].put(key, cs);
- }
- }
- }
- } else {
- synchronized (mAccessLock) {
- caches.put(key, theme, cs, usesTheme);
- }
- }
- }
-
- /**
- * Loads a drawable from XML or resources stream.
- */
- private Drawable loadDrawableForCookie(TypedValue value, int id, Theme theme) {
- if (value.string == null) {
- throw new NotFoundException("Resource \"" + getResourceName(id) + "\" ("
- + Integer.toHexString(id) + ") is not a Drawable (color or path): " + value);
- }
-
- final String file = value.string.toString();
-
- if (TRACE_FOR_MISS_PRELOAD) {
- // Log only framework resources
- if ((id >>> 24) == 0x1) {
- final String name = getResourceName(id);
- if (name != null) {
- Log.d(TAG, "Loading framework drawable #" + Integer.toHexString(id)
- + ": " + name + " at " + file);
- }
- }
- }
-
- if (DEBUG_LOAD) {
- Log.v(TAG, "Loading drawable for cookie " + value.assetCookie + ": " + file);
- }
-
- final Drawable dr;
-
- Trace.traceBegin(Trace.TRACE_TAG_RESOURCES, file);
- try {
- if (file.endsWith(".xml")) {
- final XmlResourceParser rp = loadXmlResourceParser(
- file, id, value.assetCookie, "drawable");
- dr = Drawable.createFromXml(this, rp, theme);
- rp.close();
- } else {
- final InputStream is = mAssets.openNonAsset(
- value.assetCookie, file, AssetManager.ACCESS_STREAMING);
- dr = Drawable.createFromResourceStream(this, value, is, file, null);
- is.close();
- }
- } catch (Exception e) {
- Trace.traceEnd(Trace.TRACE_TAG_RESOURCES);
- final NotFoundException rnf = new NotFoundException(
- "File " + file + " from drawable resource ID #0x" + Integer.toHexString(id));
- rnf.initCause(e);
- throw rnf;
- }
- Trace.traceEnd(Trace.TRACE_TAG_RESOURCES);
-
- return dr;
- }
-
- /**
- * Given the value and id, we can get the XML filename as in value.data, based on that, we
- * first try to load CSL from the cache. If not found, try to get from the constant state.
- * Last, parse the XML and generate the CSL.
- */
- private ComplexColor loadComplexColorFromName(Theme theme, TypedValue value, int id) {
- final long key = (((long) value.assetCookie) << 32) | value.data;
- final ConfigurationBoundResourceCache<ComplexColor> cache = mComplexColorCache;
- ComplexColor complexColor = cache.getInstance(key, theme);
- if (complexColor != null) {
- return complexColor;
- }
-
- final android.content.res.ConstantState<ComplexColor> factory =
- sPreloadedComplexColors.get(key);
-
- if (factory != null) {
- complexColor = factory.newInstance(this, theme);
- }
- if (complexColor == null) {
- complexColor = loadComplexColorForCookie(value, id, theme);
- }
-
- if (complexColor != null) {
- if (mPreloading) {
- if (verifyPreloadConfig(value.changingConfigurations, 0, value.resourceId,
- "color")) {
- sPreloadedComplexColors.put(key, complexColor.getConstantState());
- }
- } else {
- cache.put(key, theme, complexColor.getConstantState());
- }
- }
- return complexColor;
- }
-
- @Nullable
- public ComplexColor loadComplexColor(@NonNull TypedValue value, int id, Theme theme) {
- if (TRACE_FOR_PRELOAD) {
- // Log only framework resources
- if ((id >>> 24) == 0x1) {
- final String name = getResourceName(id);
- if (name != null) android.util.Log.d("loadComplexColor", name);
- }
- }
-
- final long key = (((long) value.assetCookie) << 32) | value.data;
-
- // Handle inline color definitions.
- if (value.type >= TypedValue.TYPE_FIRST_COLOR_INT
- && value.type <= TypedValue.TYPE_LAST_COLOR_INT) {
- return getColorStateListFromInt(value, key);
- }
-
- final String file = value.string.toString();
-
- ComplexColor complexColor;
- if (file.endsWith(".xml")) {
- try {
- complexColor = loadComplexColorFromName(theme, value, id);
- } catch (Exception e) {
- final NotFoundException rnf = new NotFoundException(
- "File " + file + " from complex color resource ID #0x"
- + Integer.toHexString(id));
- rnf.initCause(e);
- throw rnf;
- }
- } else {
- throw new NotFoundException(
- "File " + file + " from drawable resource ID #0x"
- + Integer.toHexString(id) + ": .xml extension required");
- }
-
- return complexColor;
- }
-
- @Nullable
- ColorStateList loadColorStateList(TypedValue value, int id, Theme theme)
- throws NotFoundException {
- if (TRACE_FOR_PRELOAD) {
- // Log only framework resources
- if ((id >>> 24) == 0x1) {
- final String name = getResourceName(id);
- if (name != null) android.util.Log.d("PreloadColorStateList", name);
- }
- }
-
- final long key = (((long) value.assetCookie) << 32) | value.data;
-
- // Handle inline color definitions.
- if (value.type >= TypedValue.TYPE_FIRST_COLOR_INT
- && value.type <= TypedValue.TYPE_LAST_COLOR_INT) {
- return getColorStateListFromInt(value, key);
- }
-
- ComplexColor complexColor = loadComplexColorFromName(theme, value, id);
- if (complexColor != null && complexColor instanceof ColorStateList) {
- return (ColorStateList) complexColor;
- }
-
- throw new NotFoundException(
- "Can't find ColorStateList from drawable resource ID #0x"
- + Integer.toHexString(id));
- }
-
- @NonNull
- private ColorStateList getColorStateListFromInt(@NonNull TypedValue value, long key) {
- ColorStateList csl;
- final android.content.res.ConstantState<ComplexColor> factory =
- sPreloadedComplexColors.get(key);
- if (factory != null) {
- return (ColorStateList) factory.newInstance();
- }
-
- csl = ColorStateList.valueOf(value.data);
-
- if (mPreloading) {
- if (verifyPreloadConfig(value.changingConfigurations, 0, value.resourceId,
- "color")) {
- sPreloadedComplexColors.put(key, csl.getConstantState());
- }
- }
-
- return csl;
- }
-
- /**
- * Load a ComplexColor based on the XML file content. The result can be a GradientColor or
- * ColorStateList. Note that pure color will be wrapped into a ColorStateList.
- *
- * We deferred the parser creation to this function b/c we need to differentiate b/t gradient
- * and selector tag.
- *
- * @return a ComplexColor (GradientColor or ColorStateList) based on the XML file content.
- */
- @Nullable
- private ComplexColor loadComplexColorForCookie(TypedValue value, int id, Theme theme) {
- if (value.string == null) {
- throw new UnsupportedOperationException(
- "Can't convert to ComplexColor: type=0x" + value.type);
- }
-
- final String file = value.string.toString();
-
- if (TRACE_FOR_MISS_PRELOAD) {
- // Log only framework resources
- if ((id >>> 24) == 0x1) {
- final String name = getResourceName(id);
- if (name != null) {
- Log.d(TAG, "Loading framework ComplexColor #" + Integer.toHexString(id)
- + ": " + name + " at " + file);
- }
- }
- }
-
- if (DEBUG_LOAD) {
- Log.v(TAG, "Loading ComplexColor for cookie " + value.assetCookie + ": " + file);
- }
-
- ComplexColor complexColor = null;
-
- Trace.traceBegin(Trace.TRACE_TAG_RESOURCES, file);
- if (file.endsWith(".xml")) {
- try {
- final XmlResourceParser parser = loadXmlResourceParser(
- file, id, value.assetCookie, "ComplexColor");
-
- final AttributeSet attrs = Xml.asAttributeSet(parser);
- int type;
- while ((type = parser.next()) != XmlPullParser.START_TAG
- && type != XmlPullParser.END_DOCUMENT) {
- // Seek parser to start tag.
- }
- if (type != XmlPullParser.START_TAG) {
- throw new XmlPullParserException("No start tag found");
- }
-
- final String name = parser.getName();
- if (name.equals("gradient")) {
- complexColor = GradientColor.createFromXmlInner(this, parser, attrs, theme);
- } else if (name.equals("selector")) {
- complexColor = ColorStateList.createFromXmlInner(this, parser, attrs, theme);
- }
- parser.close();
- } catch (Exception e) {
- Trace.traceEnd(Trace.TRACE_TAG_RESOURCES);
- final NotFoundException rnf = new NotFoundException(
- "File " + file + " from ComplexColor resource ID #0x"
- + Integer.toHexString(id));
- rnf.initCause(e);
- throw rnf;
- }
- } else {
- Trace.traceEnd(Trace.TRACE_TAG_RESOURCES);
- throw new NotFoundException(
- "File " + file + " from drawable resource ID #0x"
- + Integer.toHexString(id) + ": .xml extension required");
- }
- Trace.traceEnd(Trace.TRACE_TAG_RESOURCES);
-
- return complexColor;
+ return mResourcesImpl.getPreloadedDrawables();
}
/**
@@ -2829,10 +2037,12 @@
@NonNull
XmlResourceParser loadXmlResourceParser(@AnyRes int id, @NonNull String type)
throws NotFoundException {
- final TypedValue value = obtainTempTypedValue(id);
+ final TypedValue value = obtainTempTypedValue();
try {
+ final ResourcesImpl impl = mResourcesImpl;
+ impl.getValue(id, value, true);
if (value.type == TypedValue.TYPE_STRING) {
- return loadXmlResourceParser(value.string.toString(), id,
+ return impl.loadXmlResourceParser(value.string.toString(), id,
value.assetCookie, type);
}
throw new NotFoundException("Resource ID #0x" + Integer.toHexString(id)
@@ -2853,49 +2063,9 @@
* @throws NotFoundException if the file could not be loaded
*/
@NonNull
- XmlResourceParser loadXmlResourceParser(@NonNull String file, @AnyRes int id,
- int assetCookie, @NonNull String type) throws NotFoundException {
- if (id != 0) {
- try {
- synchronized (mCachedXmlBlocks) {
- final int[] cachedXmlBlockCookies = mCachedXmlBlockCookies;
- final String[] cachedXmlBlockFiles = mCachedXmlBlockFiles;
- final XmlBlock[] cachedXmlBlocks = mCachedXmlBlocks;
- // First see if this block is in our cache.
- final int num = cachedXmlBlockFiles.length;
- for (int i = 0; i < num; i++) {
- if (cachedXmlBlockCookies[i] == assetCookie && cachedXmlBlockFiles[i] != null
- && cachedXmlBlockFiles[i].equals(file)) {
- return cachedXmlBlocks[i].newParser();
- }
- }
-
- // Not in the cache, create a new block and put it at
- // the next slot in the cache.
- final XmlBlock block = mAssets.openXmlBlockAsset(assetCookie, file);
- if (block != null) {
- final int pos = (mLastCachedXmlBlockIndex + 1) % num;
- mLastCachedXmlBlockIndex = pos;
- final XmlBlock oldBlock = cachedXmlBlocks[pos];
- if (oldBlock != null) {
- oldBlock.close();
- }
- cachedXmlBlockCookies[pos] = assetCookie;
- cachedXmlBlockFiles[pos] = file;
- cachedXmlBlocks[pos] = block;
- return block.newParser();
- }
- }
- } catch (Exception e) {
- final NotFoundException rnf = new NotFoundException("File " + file
- + " from xml type " + type + " resource ID #0x" + Integer.toHexString(id));
- rnf.initCause(e);
- throw rnf;
- }
- }
-
- throw new NotFoundException("File " + file + " from xml type " + type + " resource ID #0x"
- + Integer.toHexString(id));
+ XmlResourceParser loadXmlResourceParser(String file, int id, int assetCookie,
+ String type) throws NotFoundException {
+ return mResourcesImpl.loadXmlResourceParser(file, id, assetCookie, type);
}
/**
@@ -2911,16 +2081,4 @@
}
return theme.obtainStyledAttributes(set, attrs, 0, 0);
}
-
- private Resources() {
- mAssets = AssetManager.getSystem();
- mClassLoader = ClassLoader.getSystemClassLoader();
- // NOTE: Intentionally leaving this uninitialized (all values set
- // to zero), so that anyone who tries to do something that requires
- // metrics will get a very wrong value.
- mConfiguration.setToDefaults();
- mMetrics.setToDefaults();
- updateConfiguration(null, null);
- mAssets.ensureStringBlocks();
- }
}
diff --git a/core/java/android/content/res/ResourcesImpl.java b/core/java/android/content/res/ResourcesImpl.java
new file mode 100644
index 0000000..2ffd372
--- /dev/null
+++ b/core/java/android/content/res/ResourcesImpl.java
@@ -0,0 +1,1140 @@
+/*
+ * 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.
+ */
+package android.content.res;
+
+import android.animation.Animator;
+import android.animation.StateListAnimator;
+import android.annotation.AnyRes;
+import android.annotation.AttrRes;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.PluralsRes;
+import android.annotation.RawRes;
+import android.annotation.StyleRes;
+import android.annotation.StyleableRes;
+import android.content.pm.ActivityInfo;
+import android.content.res.Resources.NotFoundException;
+import android.graphics.drawable.ColorDrawable;
+import android.graphics.drawable.Drawable;
+import android.icu.text.PluralRules;
+import android.os.Build;
+import android.os.Trace;
+import android.util.AttributeSet;
+import android.util.DisplayMetrics;
+import android.util.LocaleList;
+import android.util.Log;
+import android.util.LongSparseArray;
+import android.util.Slog;
+import android.util.TypedValue;
+import android.util.Xml;
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.InputStream;
+import java.util.Arrays;
+import java.util.Locale;
+
+/**
+ * @hide
+ */
+public class ResourcesImpl {
+ static final String TAG = "Resources";
+
+ private static final boolean DEBUG_LOAD = false;
+ private static final boolean DEBUG_CONFIG = false;
+ private static final boolean TRACE_FOR_PRELOAD = false;
+ private static final boolean TRACE_FOR_MISS_PRELOAD = false;
+
+ private static final int LAYOUT_DIR_CONFIG = ActivityInfo.activityInfoConfigToNative(
+ ActivityInfo.CONFIG_LAYOUT_DIRECTION);
+
+ private static final int ID_OTHER = 0x01000004;
+
+ private static final Object sSync = new Object();
+
+ private static boolean sPreloaded;
+ private boolean mPreloading;
+
+ // Information about preloaded resources. Note that they are not
+ // protected by a lock, because while preloading in zygote we are all
+ // single-threaded, and after that these are immutable.
+ private static final LongSparseArray<Drawable.ConstantState>[] sPreloadedDrawables;
+ private static final LongSparseArray<Drawable.ConstantState> sPreloadedColorDrawables
+ = new LongSparseArray<>();
+ private static final LongSparseArray<android.content.res.ConstantState<ComplexColor>>
+ sPreloadedComplexColors = new LongSparseArray<>();
+
+ /** Lock object used to protect access to caches and configuration. */
+ private final Object mAccessLock = new Object();
+
+ // These are protected by mAccessLock.
+ private final Configuration mTmpConfig = new Configuration();
+ private final DrawableCache mDrawableCache = new DrawableCache();
+ private final DrawableCache mColorDrawableCache = new DrawableCache();
+ private final ConfigurationBoundResourceCache<ComplexColor> mComplexColorCache =
+ new ConfigurationBoundResourceCache<>();
+ private final ConfigurationBoundResourceCache<Animator> mAnimatorCache =
+ new ConfigurationBoundResourceCache<>();
+ private final ConfigurationBoundResourceCache<StateListAnimator> mStateListAnimatorCache =
+ new ConfigurationBoundResourceCache<>();
+
+ /** Size of the cyclical cache used to map XML files to blocks. */
+ private static final int XML_BLOCK_CACHE_SIZE = 4;
+
+ // Cyclical cache used for recently-accessed XML files.
+ private int mLastCachedXmlBlockIndex = -1;
+ private final int[] mCachedXmlBlockCookies = new int[XML_BLOCK_CACHE_SIZE];
+ private final String[] mCachedXmlBlockFiles = new String[XML_BLOCK_CACHE_SIZE];
+ private final XmlBlock[] mCachedXmlBlocks = new XmlBlock[XML_BLOCK_CACHE_SIZE];
+
+
+ final AssetManager mAssets;
+ final DisplayMetrics mMetrics = new DisplayMetrics();
+
+ private PluralRules mPluralRule;
+
+ private final Configuration mConfiguration = new Configuration();
+ private CompatibilityInfo mCompatibilityInfo = CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO;
+
+ static {
+ sPreloadedDrawables = new LongSparseArray[2];
+ sPreloadedDrawables[0] = new LongSparseArray<>();
+ sPreloadedDrawables[1] = new LongSparseArray<>();
+ }
+
+ /**
+ * Creates a new ResourcesImpl object with CompatibilityInfo.
+ *
+ * @param assets Previously created AssetManager.
+ * @param metrics Current display metrics to consider when
+ * selecting/computing resource values.
+ * @param config Desired device configuration to consider when
+ * selecting/computing resource values (optional).
+ * @param compatInfo this resource's compatibility info. Must not be null.
+ */
+ public ResourcesImpl(AssetManager assets, DisplayMetrics metrics, Configuration config,
+ CompatibilityInfo compatInfo) {
+ mAssets = assets;
+ mMetrics.setToDefaults();
+ updateConfiguration(config, metrics, compatInfo);
+ mAssets.ensureStringBlocks();
+ }
+
+ AssetManager getAssets() {
+ return mAssets;
+ }
+
+ DisplayMetrics getDisplayMetrics() {
+ if (DEBUG_CONFIG) Slog.v(TAG, "Returning DisplayMetrics: " + mMetrics.widthPixels
+ + "x" + mMetrics.heightPixels + " " + mMetrics.density);
+ return mMetrics;
+ }
+
+ Configuration getConfiguration() {
+ return mConfiguration;
+ }
+
+ Configuration[] getSizeConfigurations() {
+ return mAssets.getSizeConfigurations();
+ }
+
+ CompatibilityInfo getCompatibilityInfo() {
+ return mCompatibilityInfo;
+ }
+
+ private PluralRules getPluralRule() {
+ synchronized (sSync) {
+ if (mPluralRule == null) {
+ mPluralRule = PluralRules.forLocale(mConfiguration.getLocales().get(0));
+ }
+ return mPluralRule;
+ }
+ }
+
+ void getValue(@AnyRes int id, TypedValue outValue, boolean resolveRefs)
+ throws NotFoundException {
+ boolean found = mAssets.getResourceValue(id, 0, outValue, resolveRefs);
+ if (found) {
+ return;
+ }
+ throw new NotFoundException("Resource ID #0x" + Integer.toHexString(id));
+ }
+
+ void getValueForDensity(@AnyRes int id, int density, TypedValue outValue,
+ boolean resolveRefs) throws NotFoundException {
+ boolean found = mAssets.getResourceValue(id, density, outValue, resolveRefs);
+ if (found) {
+ return;
+ }
+ throw new NotFoundException("Resource ID #0x" + Integer.toHexString(id));
+ }
+
+ void getValue(String name, TypedValue outValue, boolean resolveRefs)
+ throws NotFoundException {
+ int id = getIdentifier(name, "string", null);
+ if (id != 0) {
+ getValue(id, outValue, resolveRefs);
+ return;
+ }
+ throw new NotFoundException("String resource name " + name);
+ }
+
+ int getIdentifier(String name, String defType, String defPackage) {
+ if (name == null) {
+ throw new NullPointerException("name is null");
+ }
+ try {
+ return Integer.parseInt(name);
+ } catch (Exception e) {
+ // Ignore
+ }
+ return mAssets.getResourceIdentifier(name, defType, defPackage);
+ }
+
+ @NonNull
+ String getResourceName(@AnyRes int resid) throws NotFoundException {
+ String str = mAssets.getResourceName(resid);
+ if (str != null) return str;
+ throw new NotFoundException("Unable to find resource ID #0x"
+ + Integer.toHexString(resid));
+ }
+
+ @NonNull
+ String getResourcePackageName(@AnyRes int resid) throws NotFoundException {
+ String str = mAssets.getResourcePackageName(resid);
+ if (str != null) return str;
+ throw new NotFoundException("Unable to find resource ID #0x"
+ + Integer.toHexString(resid));
+ }
+
+ @NonNull
+ String getResourceTypeName(@AnyRes int resid) throws NotFoundException {
+ String str = mAssets.getResourceTypeName(resid);
+ if (str != null) return str;
+ throw new NotFoundException("Unable to find resource ID #0x"
+ + Integer.toHexString(resid));
+ }
+
+ @NonNull
+ String getResourceEntryName(@AnyRes int resid) throws NotFoundException {
+ String str = mAssets.getResourceEntryName(resid);
+ if (str != null) return str;
+ throw new NotFoundException("Unable to find resource ID #0x"
+ + Integer.toHexString(resid));
+ }
+
+ @NonNull
+ CharSequence getQuantityText(@PluralsRes int id, int quantity) throws NotFoundException {
+ PluralRules rule = getPluralRule();
+ CharSequence res = mAssets.getResourceBagText(id,
+ attrForQuantityCode(rule.select(quantity)));
+ if (res != null) {
+ return res;
+ }
+ res = mAssets.getResourceBagText(id, ID_OTHER);
+ if (res != null) {
+ return res;
+ }
+ throw new NotFoundException("Plural resource ID #0x" + Integer.toHexString(id)
+ + " quantity=" + quantity
+ + " item=" + rule.select(quantity));
+ }
+
+ private static int attrForQuantityCode(String quantityCode) {
+ switch (quantityCode) {
+ case PluralRules.KEYWORD_ZERO: return 0x01000005;
+ case PluralRules.KEYWORD_ONE: return 0x01000006;
+ case PluralRules.KEYWORD_TWO: return 0x01000007;
+ case PluralRules.KEYWORD_FEW: return 0x01000008;
+ case PluralRules.KEYWORD_MANY: return 0x01000009;
+ default: return ID_OTHER;
+ }
+ }
+
+ @NonNull
+ AssetFileDescriptor openRawResourceFd(@RawRes int id, TypedValue tempValue)
+ throws NotFoundException {
+ getValue(id, tempValue, true);
+ try {
+ return mAssets.openNonAssetFd(tempValue.assetCookie, tempValue.string.toString());
+ } catch (Exception e) {
+ throw new NotFoundException("File " + tempValue.string.toString() + " from drawable "
+ + "resource ID #0x" + Integer.toHexString(id), e);
+ }
+ }
+
+ @NonNull
+ InputStream openRawResource(@RawRes int id, TypedValue value) throws NotFoundException {
+ getValue(id, value, true);
+ try {
+ return mAssets.openNonAsset(value.assetCookie, value.string.toString(),
+ AssetManager.ACCESS_STREAMING);
+ } catch (Exception e) {
+ NotFoundException rnf = new NotFoundException("File " + value.string.toString() +
+ " from drawable resource ID #0x" + Integer.toHexString(id));
+ rnf.initCause(e);
+ throw rnf;
+ }
+ }
+
+ ConfigurationBoundResourceCache<Animator> getAnimatorCache() {
+ return mAnimatorCache;
+ }
+
+ ConfigurationBoundResourceCache<StateListAnimator> getStateListAnimatorCache() {
+ return mStateListAnimatorCache;
+ }
+
+ void updateConfiguration(Configuration config, DisplayMetrics metrics,
+ CompatibilityInfo compat) {
+ synchronized (mAccessLock) {
+ if (false) {
+ Slog.i(TAG, "**** Updating config of " + this + ": old config is "
+ + mConfiguration + " old compat is " + mCompatibilityInfo);
+ Slog.i(TAG, "**** Updating config of " + this + ": new config is "
+ + config + " new compat is " + compat);
+ }
+ if (compat != null) {
+ mCompatibilityInfo = compat;
+ }
+ if (metrics != null) {
+ mMetrics.setTo(metrics);
+ }
+ // NOTE: We should re-arrange this code to create a Display
+ // with the CompatibilityInfo that is used everywhere we deal
+ // with the display in relation to this app, rather than
+ // doing the conversion here. This impl should be okay because
+ // we make sure to return a compatible display in the places
+ // where there are public APIs to retrieve the display... but
+ // it would be cleaner and more maintainble to just be
+ // consistently dealing with a compatible display everywhere in
+ // the framework.
+ mCompatibilityInfo.applyToDisplayMetrics(mMetrics);
+
+ final int configChanges = calcConfigChanges(config);
+
+ LocaleList locales = mConfiguration.getLocales();
+ if (locales.isEmpty()) {
+ locales = LocaleList.getAdjustedDefault();
+ mConfiguration.setLocales(locales);
+ }
+ if (mConfiguration.densityDpi != Configuration.DENSITY_DPI_UNDEFINED) {
+ mMetrics.densityDpi = mConfiguration.densityDpi;
+ mMetrics.density = mConfiguration.densityDpi * DisplayMetrics.DENSITY_DEFAULT_SCALE;
+ }
+ mMetrics.scaledDensity = mMetrics.density * mConfiguration.fontScale;
+
+ final int width, height;
+ if (mMetrics.widthPixels >= mMetrics.heightPixels) {
+ width = mMetrics.widthPixels;
+ height = mMetrics.heightPixels;
+ } else {
+ //noinspection SuspiciousNameCombination
+ width = mMetrics.heightPixels;
+ //noinspection SuspiciousNameCombination
+ height = mMetrics.widthPixels;
+ }
+
+ final int keyboardHidden;
+ if (mConfiguration.keyboardHidden == Configuration.KEYBOARDHIDDEN_NO
+ && mConfiguration.hardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_YES) {
+ keyboardHidden = Configuration.KEYBOARDHIDDEN_SOFT;
+ } else {
+ keyboardHidden = mConfiguration.keyboardHidden;
+ }
+
+ mAssets.setConfiguration(mConfiguration.mcc, mConfiguration.mnc,
+ adjustLanguageTag(locales.get(0).toLanguageTag()),
+ mConfiguration.orientation,
+ mConfiguration.touchscreen,
+ mConfiguration.densityDpi, mConfiguration.keyboard,
+ keyboardHidden, mConfiguration.navigation, width, height,
+ mConfiguration.smallestScreenWidthDp,
+ mConfiguration.screenWidthDp, mConfiguration.screenHeightDp,
+ mConfiguration.screenLayout, mConfiguration.uiMode,
+ Build.VERSION.RESOURCES_SDK_INT);
+
+ if (DEBUG_CONFIG) {
+ Slog.i(TAG, "**** Updating config of " + this + ": final config is "
+ + mConfiguration + " final compat is " + mCompatibilityInfo);
+ }
+
+ mDrawableCache.onConfigurationChange(configChanges);
+ mColorDrawableCache.onConfigurationChange(configChanges);
+ mComplexColorCache.onConfigurationChange(configChanges);
+ mAnimatorCache.onConfigurationChange(configChanges);
+ mStateListAnimatorCache.onConfigurationChange(configChanges);
+
+ flushLayoutCache();
+ }
+ synchronized (sSync) {
+ if (mPluralRule != null) {
+ mPluralRule = PluralRules.forLocale(mConfiguration.getLocales().get(0));
+ }
+ }
+ }
+
+ /**
+ * Called by ConfigurationBoundResourceCacheTest via reflection.
+ */
+ private int calcConfigChanges(Configuration config) {
+ int configChanges = 0xfffffff;
+ if (config != null) {
+ mTmpConfig.setTo(config);
+ int density = config.densityDpi;
+ if (density == Configuration.DENSITY_DPI_UNDEFINED) {
+ density = mMetrics.noncompatDensityDpi;
+ }
+
+ mCompatibilityInfo.applyToConfiguration(density, mTmpConfig);
+
+ if (mTmpConfig.getLocales().isEmpty()) {
+ mTmpConfig.setLocales(LocaleList.getDefault());
+ }
+ configChanges = mConfiguration.updateFrom(mTmpConfig);
+ configChanges = ActivityInfo.activityInfoConfigToNative(configChanges);
+ }
+ return configChanges;
+ }
+
+ /**
+ * {@code Locale.toLanguageTag} will transform the obsolete (and deprecated)
+ * language codes "in", "ji" and "iw" to "id", "yi" and "he" respectively.
+ *
+ * All released versions of android prior to "L" used the deprecated language
+ * tags, so we will need to support them for backwards compatibility.
+ *
+ * Note that this conversion needs to take place *after* the call to
+ * {@code toLanguageTag} because that will convert all the deprecated codes to
+ * the new ones, even if they're set manually.
+ */
+ private static String adjustLanguageTag(String languageTag) {
+ final int separator = languageTag.indexOf('-');
+ final String language;
+ final String remainder;
+
+ if (separator == -1) {
+ language = languageTag;
+ remainder = "";
+ } else {
+ language = languageTag.substring(0, separator);
+ remainder = languageTag.substring(separator);
+ }
+
+ return Locale.adjustLanguageCode(language) + remainder;
+ }
+
+ /**
+ * Call this to remove all cached loaded layout resources from the
+ * Resources object. Only intended for use with performance testing
+ * tools.
+ */
+ public void flushLayoutCache() {
+ synchronized (mCachedXmlBlocks) {
+ Arrays.fill(mCachedXmlBlockCookies, 0);
+ Arrays.fill(mCachedXmlBlockFiles, null);
+
+ final XmlBlock[] cachedXmlBlocks = mCachedXmlBlocks;
+ for (int i = 0; i < XML_BLOCK_CACHE_SIZE; i++) {
+ final XmlBlock oldBlock = cachedXmlBlocks[i];
+ if (oldBlock != null) {
+ oldBlock.close();
+ }
+ }
+ Arrays.fill(cachedXmlBlocks, null);
+ }
+ }
+
+ @Nullable
+ Drawable loadDrawable(Resources wrapper, TypedValue value, int id, Resources.Theme theme,
+ boolean useCache) throws NotFoundException {
+ try {
+ if (TRACE_FOR_PRELOAD) {
+ // Log only framework resources
+ if ((id >>> 24) == 0x1) {
+ final String name = getResourceName(id);
+ if (name != null) {
+ Log.d("PreloadDrawable", name);
+ }
+ }
+ }
+
+ final boolean isColorDrawable;
+ final DrawableCache caches;
+ final long key;
+ if (value.type >= TypedValue.TYPE_FIRST_COLOR_INT
+ && value.type <= TypedValue.TYPE_LAST_COLOR_INT) {
+ isColorDrawable = true;
+ caches = mColorDrawableCache;
+ key = value.data;
+ } else {
+ isColorDrawable = false;
+ caches = mDrawableCache;
+ key = (((long) value.assetCookie) << 32) | value.data;
+ }
+
+ // First, check whether we have a cached version of this drawable
+ // that was inflated against the specified theme. Skip the cache if
+ // we're currently preloading or we're not using the cache.
+ if (!mPreloading && useCache) {
+ final Drawable cachedDrawable = caches.getInstance(key, wrapper, theme);
+ if (cachedDrawable != null) {
+ return cachedDrawable;
+ }
+ }
+
+ // Next, check preloaded drawables. Preloaded drawables may contain
+ // unresolved theme attributes.
+ final Drawable.ConstantState cs;
+ if (isColorDrawable) {
+ cs = sPreloadedColorDrawables.get(key);
+ } else {
+ cs = sPreloadedDrawables[mConfiguration.getLayoutDirection()].get(key);
+ }
+
+ Drawable dr;
+ if (cs != null) {
+ dr = cs.newDrawable(wrapper);
+ } else if (isColorDrawable) {
+ dr = new ColorDrawable(value.data);
+ } else {
+ dr = loadDrawableForCookie(wrapper, value, id, null);
+ }
+
+ // Determine if the drawable has unresolved theme attributes. If it
+ // does, we'll need to apply a theme and store it in a theme-specific
+ // cache.
+ final boolean canApplyTheme = dr != null && dr.canApplyTheme();
+ if (canApplyTheme && theme != null) {
+ dr = dr.mutate();
+ dr.applyTheme(theme);
+ dr.clearMutated();
+ }
+
+ // If we were able to obtain a drawable, store it in the appropriate
+ // cache: preload, not themed, null theme, or theme-specific. Don't
+ // pollute the cache with drawables loaded from a foreign density.
+ if (dr != null && useCache) {
+ dr.setChangingConfigurations(value.changingConfigurations);
+ cacheDrawable(value, isColorDrawable, caches, theme, canApplyTheme, key, dr);
+ }
+
+ return dr;
+ } catch (Exception e) {
+ String name;
+ try {
+ name = getResourceName(id);
+ } catch (NotFoundException e2) {
+ name = "(missing name)";
+ }
+
+ // The target drawable might fail to load for any number of
+ // reasons, but we always want to include the resource name.
+ // Since the client already expects this method to throw a
+ // NotFoundException, just throw one of those.
+ final NotFoundException nfe = new NotFoundException("Drawable " + name
+ + " with resource ID #0x" + Integer.toHexString(id), e);
+ nfe.setStackTrace(new StackTraceElement[0]);
+ throw nfe;
+ }
+ }
+
+ private void cacheDrawable(TypedValue value, boolean isColorDrawable, DrawableCache caches,
+ Resources.Theme theme, boolean usesTheme, long key, Drawable dr) {
+ final Drawable.ConstantState cs = dr.getConstantState();
+ if (cs == null) {
+ return;
+ }
+
+ if (mPreloading) {
+ final int changingConfigs = cs.getChangingConfigurations();
+ if (isColorDrawable) {
+ if (verifyPreloadConfig(changingConfigs, 0, value.resourceId, "drawable")) {
+ sPreloadedColorDrawables.put(key, cs);
+ }
+ } else {
+ if (verifyPreloadConfig(
+ changingConfigs, LAYOUT_DIR_CONFIG, value.resourceId, "drawable")) {
+ if ((changingConfigs & LAYOUT_DIR_CONFIG) == 0) {
+ // If this resource does not vary based on layout direction,
+ // we can put it in all of the preload maps.
+ sPreloadedDrawables[0].put(key, cs);
+ sPreloadedDrawables[1].put(key, cs);
+ } else {
+ // Otherwise, only in the layout dir we loaded it for.
+ sPreloadedDrawables[mConfiguration.getLayoutDirection()].put(key, cs);
+ }
+ }
+ }
+ } else {
+ synchronized (mAccessLock) {
+ caches.put(key, theme, cs, usesTheme);
+ }
+ }
+ }
+
+ private boolean verifyPreloadConfig(int changingConfigurations, int allowVarying,
+ int resourceId, String name) {
+ // We allow preloading of resources even if they vary by font scale (which
+ // doesn't impact resource selection) or density (which we handle specially by
+ // simply turning off all preloading), as well as any other configs specified
+ // by the caller.
+ if (((changingConfigurations&~(ActivityInfo.CONFIG_FONT_SCALE |
+ ActivityInfo.CONFIG_DENSITY)) & ~allowVarying) != 0) {
+ String resName;
+ try {
+ resName = getResourceName(resourceId);
+ } catch (NotFoundException e) {
+ resName = "?";
+ }
+ // This should never happen in production, so we should log a
+ // warning even if we're not debugging.
+ Log.w(TAG, "Preloaded " + name + " resource #0x"
+ + Integer.toHexString(resourceId)
+ + " (" + resName + ") that varies with configuration!!");
+ return false;
+ }
+ if (TRACE_FOR_PRELOAD) {
+ String resName;
+ try {
+ resName = getResourceName(resourceId);
+ } catch (NotFoundException e) {
+ resName = "?";
+ }
+ Log.w(TAG, "Preloading " + name + " resource #0x"
+ + Integer.toHexString(resourceId)
+ + " (" + resName + ")");
+ }
+ return true;
+ }
+
+ /**
+ * Loads a drawable from XML or resources stream.
+ */
+ private Drawable loadDrawableForCookie(Resources wrapper, TypedValue value, int id,
+ Resources.Theme theme) {
+ if (value.string == null) {
+ throw new NotFoundException("Resource \"" + getResourceName(id) + "\" ("
+ + Integer.toHexString(id) + ") is not a Drawable (color or path): " + value);
+ }
+
+ final String file = value.string.toString();
+
+ if (TRACE_FOR_MISS_PRELOAD) {
+ // Log only framework resources
+ if ((id >>> 24) == 0x1) {
+ final String name = getResourceName(id);
+ if (name != null) {
+ Log.d(TAG, "Loading framework drawable #" + Integer.toHexString(id)
+ + ": " + name + " at " + file);
+ }
+ }
+ }
+
+ if (DEBUG_LOAD) {
+ Log.v(TAG, "Loading drawable for cookie " + value.assetCookie + ": " + file);
+ }
+
+ final Drawable dr;
+
+ Trace.traceBegin(Trace.TRACE_TAG_RESOURCES, file);
+ try {
+ if (file.endsWith(".xml")) {
+ final XmlResourceParser rp = loadXmlResourceParser(
+ file, id, value.assetCookie, "drawable");
+ dr = Drawable.createFromXml(wrapper, rp, theme);
+ rp.close();
+ } else {
+ final InputStream is = mAssets.openNonAsset(
+ value.assetCookie, file, AssetManager.ACCESS_STREAMING);
+ dr = Drawable.createFromResourceStream(wrapper, value, is, file, null);
+ is.close();
+ }
+ } catch (Exception e) {
+ Trace.traceEnd(Trace.TRACE_TAG_RESOURCES);
+ final NotFoundException rnf = new NotFoundException(
+ "File " + file + " from drawable resource ID #0x" + Integer.toHexString(id));
+ rnf.initCause(e);
+ throw rnf;
+ }
+ Trace.traceEnd(Trace.TRACE_TAG_RESOURCES);
+
+ return dr;
+ }
+
+ /**
+ * Given the value and id, we can get the XML filename as in value.data, based on that, we
+ * first try to load CSL from the cache. If not found, try to get from the constant state.
+ * Last, parse the XML and generate the CSL.
+ */
+ private ComplexColor loadComplexColorFromName(Resources wrapper, Resources.Theme theme,
+ TypedValue value, int id) {
+ final long key = (((long) value.assetCookie) << 32) | value.data;
+ final ConfigurationBoundResourceCache<ComplexColor> cache = mComplexColorCache;
+ ComplexColor complexColor = cache.getInstance(key, wrapper, theme);
+ if (complexColor != null) {
+ return complexColor;
+ }
+
+ final android.content.res.ConstantState<ComplexColor> factory =
+ sPreloadedComplexColors.get(key);
+
+ if (factory != null) {
+ complexColor = factory.newInstance(wrapper, theme);
+ }
+ if (complexColor == null) {
+ complexColor = loadComplexColorForCookie(wrapper, value, id, theme);
+ }
+
+ if (complexColor != null) {
+ if (mPreloading) {
+ if (verifyPreloadConfig(value.changingConfigurations, 0, value.resourceId,
+ "color")) {
+ sPreloadedComplexColors.put(key, complexColor.getConstantState());
+ }
+ } else {
+ cache.put(key, theme, complexColor.getConstantState());
+ }
+ }
+ return complexColor;
+ }
+
+ @Nullable
+ ComplexColor loadComplexColor(Resources wrapper, @NonNull TypedValue value, int id,
+ Resources.Theme theme) {
+ if (TRACE_FOR_PRELOAD) {
+ // Log only framework resources
+ if ((id >>> 24) == 0x1) {
+ final String name = getResourceName(id);
+ if (name != null) android.util.Log.d("loadComplexColor", name);
+ }
+ }
+
+ final long key = (((long) value.assetCookie) << 32) | value.data;
+
+ // Handle inline color definitions.
+ if (value.type >= TypedValue.TYPE_FIRST_COLOR_INT
+ && value.type <= TypedValue.TYPE_LAST_COLOR_INT) {
+ return getColorStateListFromInt(value, key);
+ }
+
+ final String file = value.string.toString();
+
+ ComplexColor complexColor;
+ if (file.endsWith(".xml")) {
+ try {
+ complexColor = loadComplexColorFromName(wrapper, theme, value, id);
+ } catch (Exception e) {
+ final NotFoundException rnf = new NotFoundException(
+ "File " + file + " from complex color resource ID #0x"
+ + Integer.toHexString(id));
+ rnf.initCause(e);
+ throw rnf;
+ }
+ } else {
+ throw new NotFoundException(
+ "File " + file + " from drawable resource ID #0x"
+ + Integer.toHexString(id) + ": .xml extension required");
+ }
+
+ return complexColor;
+ }
+
+ @Nullable
+ ColorStateList loadColorStateList(Resources wrapper, TypedValue value, int id,
+ Resources.Theme theme)
+ throws NotFoundException {
+ if (TRACE_FOR_PRELOAD) {
+ // Log only framework resources
+ if ((id >>> 24) == 0x1) {
+ final String name = getResourceName(id);
+ if (name != null) android.util.Log.d("PreloadColorStateList", name);
+ }
+ }
+
+ final long key = (((long) value.assetCookie) << 32) | value.data;
+
+ // Handle inline color definitions.
+ if (value.type >= TypedValue.TYPE_FIRST_COLOR_INT
+ && value.type <= TypedValue.TYPE_LAST_COLOR_INT) {
+ return getColorStateListFromInt(value, key);
+ }
+
+ ComplexColor complexColor = loadComplexColorFromName(wrapper, theme, value, id);
+ if (complexColor != null && complexColor instanceof ColorStateList) {
+ return (ColorStateList) complexColor;
+ }
+
+ throw new NotFoundException(
+ "Can't find ColorStateList from drawable resource ID #0x"
+ + Integer.toHexString(id));
+ }
+
+ @NonNull
+ private ColorStateList getColorStateListFromInt(@NonNull TypedValue value, long key) {
+ ColorStateList csl;
+ final android.content.res.ConstantState<ComplexColor> factory =
+ sPreloadedComplexColors.get(key);
+ if (factory != null) {
+ return (ColorStateList) factory.newInstance();
+ }
+
+ csl = ColorStateList.valueOf(value.data);
+
+ if (mPreloading) {
+ if (verifyPreloadConfig(value.changingConfigurations, 0, value.resourceId,
+ "color")) {
+ sPreloadedComplexColors.put(key, csl.getConstantState());
+ }
+ }
+
+ return csl;
+ }
+
+ /**
+ * Load a ComplexColor based on the XML file content. The result can be a GradientColor or
+ * ColorStateList. Note that pure color will be wrapped into a ColorStateList.
+ *
+ * We deferred the parser creation to this function b/c we need to differentiate b/t gradient
+ * and selector tag.
+ *
+ * @return a ComplexColor (GradientColor or ColorStateList) based on the XML file content.
+ */
+ @Nullable
+ private ComplexColor loadComplexColorForCookie(Resources wrapper, TypedValue value, int id,
+ Resources.Theme theme) {
+ if (value.string == null) {
+ throw new UnsupportedOperationException(
+ "Can't convert to ComplexColor: type=0x" + value.type);
+ }
+
+ final String file = value.string.toString();
+
+ if (TRACE_FOR_MISS_PRELOAD) {
+ // Log only framework resources
+ if ((id >>> 24) == 0x1) {
+ final String name = getResourceName(id);
+ if (name != null) {
+ Log.d(TAG, "Loading framework ComplexColor #" + Integer.toHexString(id)
+ + ": " + name + " at " + file);
+ }
+ }
+ }
+
+ if (DEBUG_LOAD) {
+ Log.v(TAG, "Loading ComplexColor for cookie " + value.assetCookie + ": " + file);
+ }
+
+ ComplexColor complexColor = null;
+
+ Trace.traceBegin(Trace.TRACE_TAG_RESOURCES, file);
+ if (file.endsWith(".xml")) {
+ try {
+ final XmlResourceParser parser = loadXmlResourceParser(
+ file, id, value.assetCookie, "ComplexColor");
+
+ final AttributeSet attrs = Xml.asAttributeSet(parser);
+ int type;
+ while ((type = parser.next()) != XmlPullParser.START_TAG
+ && type != XmlPullParser.END_DOCUMENT) {
+ // Seek parser to start tag.
+ }
+ if (type != XmlPullParser.START_TAG) {
+ throw new XmlPullParserException("No start tag found");
+ }
+
+ final String name = parser.getName();
+ if (name.equals("gradient")) {
+ complexColor = GradientColor.createFromXmlInner(wrapper, parser, attrs, theme);
+ } else if (name.equals("selector")) {
+ complexColor = ColorStateList.createFromXmlInner(wrapper, parser, attrs, theme);
+ }
+ parser.close();
+ } catch (Exception e) {
+ Trace.traceEnd(Trace.TRACE_TAG_RESOURCES);
+ final NotFoundException rnf = new NotFoundException(
+ "File " + file + " from ComplexColor resource ID #0x"
+ + Integer.toHexString(id));
+ rnf.initCause(e);
+ throw rnf;
+ }
+ } else {
+ Trace.traceEnd(Trace.TRACE_TAG_RESOURCES);
+ throw new NotFoundException(
+ "File " + file + " from drawable resource ID #0x"
+ + Integer.toHexString(id) + ": .xml extension required");
+ }
+ Trace.traceEnd(Trace.TRACE_TAG_RESOURCES);
+
+ return complexColor;
+ }
+
+ /**
+ * Loads an XML parser for the specified file.
+ *
+ * @param file the path for the XML file to parse
+ * @param id the resource identifier for the file
+ * @param assetCookie the asset cookie for the file
+ * @param type the type of resource (used for logging)
+ * @return a parser for the specified XML file
+ * @throws NotFoundException if the file could not be loaded
+ */
+ @NonNull
+ XmlResourceParser loadXmlResourceParser(@NonNull String file, @AnyRes int id,
+ int assetCookie, @NonNull String type)
+ throws NotFoundException {
+ if (id != 0) {
+ try {
+ synchronized (mCachedXmlBlocks) {
+ final int[] cachedXmlBlockCookies = mCachedXmlBlockCookies;
+ final String[] cachedXmlBlockFiles = mCachedXmlBlockFiles;
+ final XmlBlock[] cachedXmlBlocks = mCachedXmlBlocks;
+ // First see if this block is in our cache.
+ final int num = cachedXmlBlockFiles.length;
+ for (int i = 0; i < num; i++) {
+ if (cachedXmlBlockCookies[i] == assetCookie && cachedXmlBlockFiles[i] != null
+ && cachedXmlBlockFiles[i].equals(file)) {
+ return cachedXmlBlocks[i].newParser();
+ }
+ }
+
+ // Not in the cache, create a new block and put it at
+ // the next slot in the cache.
+ final XmlBlock block = mAssets.openXmlBlockAsset(assetCookie, file);
+ if (block != null) {
+ final int pos = (mLastCachedXmlBlockIndex + 1) % num;
+ mLastCachedXmlBlockIndex = pos;
+ final XmlBlock oldBlock = cachedXmlBlocks[pos];
+ if (oldBlock != null) {
+ oldBlock.close();
+ }
+ cachedXmlBlockCookies[pos] = assetCookie;
+ cachedXmlBlockFiles[pos] = file;
+ cachedXmlBlocks[pos] = block;
+ return block.newParser();
+ }
+ }
+ } catch (Exception e) {
+ final NotFoundException rnf = new NotFoundException("File " + file
+ + " from xml type " + type + " resource ID #0x" + Integer.toHexString(id));
+ rnf.initCause(e);
+ throw rnf;
+ }
+ }
+
+ throw new NotFoundException("File " + file + " from xml type " + type + " resource ID #0x"
+ + Integer.toHexString(id));
+ }
+
+ /**
+ * Start preloading of resource data using this Resources object. Only
+ * for use by the zygote process for loading common system resources.
+ * {@hide}
+ */
+ public final void startPreloading() {
+ synchronized (sSync) {
+ if (sPreloaded) {
+ throw new IllegalStateException("Resources already preloaded");
+ }
+ sPreloaded = true;
+ mPreloading = true;
+ mConfiguration.densityDpi = DisplayMetrics.DENSITY_DEVICE;
+ updateConfiguration(null, null, null);
+ }
+ }
+
+ /**
+ * Called by zygote when it is done preloading resources, to change back
+ * to normal Resources operation.
+ */
+ void finishPreloading() {
+ if (mPreloading) {
+ mPreloading = false;
+ flushLayoutCache();
+ }
+ }
+
+ LongSparseArray<Drawable.ConstantState> getPreloadedDrawables() {
+ return sPreloadedDrawables[0];
+ }
+
+ ThemeImpl newThemeImpl() {
+ return new ThemeImpl();
+ }
+
+ public class ThemeImpl {
+ /**
+ * Unique key for the series of styles applied to this theme.
+ */
+ private final Resources.ThemeKey mKey = new Resources.ThemeKey();
+
+ @SuppressWarnings("hiding")
+ private final AssetManager mAssets;
+ private final long mTheme;
+
+ /**
+ * Resource identifier for the theme.
+ */
+ private int mThemeResId = 0;
+
+ /*package*/ ThemeImpl() {
+ mAssets = ResourcesImpl.this.mAssets;
+ mTheme = mAssets.createTheme();
+ }
+
+ @Override
+ protected void finalize() throws Throwable {
+ super.finalize();
+ mAssets.releaseTheme(mTheme);
+ }
+
+ /*package*/ Resources.ThemeKey getKey() {
+ return mKey;
+ }
+
+ /*package*/ long getNativeTheme() {
+ return mTheme;
+ }
+
+ /*package*/ int getAppliedStyleResId() {
+ return mThemeResId;
+ }
+
+ void applyStyle(int resId, boolean force) {
+ synchronized (mKey) {
+ AssetManager.applyThemeStyle(mTheme, resId, force);
+
+ mThemeResId = resId;
+ mKey.append(resId, force);
+ }
+ }
+
+ void setTo(ThemeImpl other) {
+ synchronized (mKey) {
+ synchronized (other.mKey) {
+ AssetManager.copyTheme(mTheme, other.mTheme);
+
+ mThemeResId = other.mThemeResId;
+ mKey.setTo(other.getKey());
+ }
+ }
+ }
+
+ @NonNull
+ TypedArray obtainStyledAttributes(@NonNull Resources.Theme wrapper,
+ AttributeSet set,
+ @StyleableRes int[] attrs,
+ @AttrRes int defStyleAttr,
+ @StyleRes int defStyleRes) {
+ synchronized (mKey) {
+ final int len = attrs.length;
+ final TypedArray array = TypedArray.obtain(wrapper.getResources(), len);
+
+ // XXX note that for now we only work with compiled XML files.
+ // To support generic XML files we will need to manually parse
+ // out the attributes from the XML file (applying type information
+ // contained in the resources and such).
+ final XmlBlock.Parser parser = (XmlBlock.Parser) set;
+ AssetManager.applyStyle(mTheme, defStyleAttr, defStyleRes,
+ parser != null ? parser.mParseState : 0,
+ attrs, array.mData, array.mIndices);
+ array.mTheme = wrapper;
+ array.mXml = parser;
+
+ return array;
+ }
+ }
+
+ @NonNull
+ TypedArray resolveAttributes(@NonNull Resources.Theme wrapper,
+ @NonNull int[] values,
+ @NonNull int[] attrs) {
+ synchronized (mKey) {
+ final int len = attrs.length;
+ if (values == null || len != values.length) {
+ throw new IllegalArgumentException(
+ "Base attribute values must the same length as attrs");
+ }
+
+ final TypedArray array = TypedArray.obtain(wrapper.getResources(), len);
+ AssetManager.resolveAttrs(mTheme, 0, 0, values, attrs, array.mData, array.mIndices);
+ array.mTheme = wrapper;
+ array.mXml = null;
+ return array;
+ }
+ }
+
+ boolean resolveAttribute(int resid, TypedValue outValue, boolean resolveRefs) {
+ synchronized (mKey) {
+ return mAssets.getThemeValue(mTheme, resid, outValue, resolveRefs);
+ }
+ }
+
+ int[] getAllAttributes() {
+ return mAssets.getStyleAttributes(getAppliedStyleResId());
+ }
+
+ int getChangingConfigurations() {
+ synchronized (mKey) {
+ final int nativeChangingConfig =
+ AssetManager.getThemeChangingConfigurations(mTheme);
+ return ActivityInfo.activityInfoConfigNativeToJava(nativeChangingConfig);
+ }
+ }
+
+ public void dump(int priority, String tag, String prefix) {
+ synchronized (mKey) {
+ AssetManager.dumpTheme(mTheme, priority, tag, prefix);
+ }
+ }
+
+ String[] getTheme() {
+ synchronized (mKey) {
+ final int N = mKey.mCount;
+ final String[] themes = new String[N * 2];
+ for (int i = 0, j = N - 1; i < themes.length; i += 2, --j) {
+ final int resId = mKey.mResId[j];
+ final boolean forced = mKey.mForce[j];
+ try {
+ themes[i] = getResourceName(resId);
+ } catch (NotFoundException e) {
+ themes[i] = Integer.toHexString(i);
+ }
+ themes[i + 1] = forced ? "forced" : "not forced";
+ }
+ return themes;
+ }
+ }
+
+ /**
+ * Rebases the theme against the parent Resource object's current
+ * configuration by re-applying the styles passed to
+ * {@link #applyStyle(int, boolean)}.
+ */
+ void rebase() {
+ synchronized (mKey) {
+ AssetManager.clearTheme(mTheme);
+
+ // Reapply the same styles in the same order.
+ for (int i = 0; i < mKey.mCount; i++) {
+ final int resId = mKey.mResId[i];
+ final boolean force = mKey.mForce[i];
+ AssetManager.applyThemeStyle(mTheme, resId, force);
+ }
+ }
+ }
+ }
+}
diff --git a/core/java/android/content/res/TypedArray.java b/core/java/android/content/res/TypedArray.java
index da49b64..022bdfb 100644
--- a/core/java/android/content/res/TypedArray.java
+++ b/core/java/android/content/res/TypedArray.java
@@ -1206,8 +1206,8 @@
/*package*/ TypedArray(Resources resources, int[] data, int[] indices, int len) {
mResources = resources;
- mMetrics = mResources.mMetrics;
- mAssets = mResources.mAssets;
+ mMetrics = mResources.getDisplayMetrics();
+ mAssets = mResources.getAssets();
mData = data;
mIndices = indices;
mLength = len;
diff --git a/core/java/android/hardware/CameraInfo.aidl b/core/java/android/hardware/CameraInfo.aidl
deleted file mode 100644
index e21e694..0000000
--- a/core/java/android/hardware/CameraInfo.aidl
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright (C) 2013 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 android.hardware;
-
-/** @hide */
-parcelable CameraInfo;
diff --git a/core/java/android/hardware/ConsumerIrManager.java b/core/java/android/hardware/ConsumerIrManager.java
index 6d29212..9fa1c3f 100644
--- a/core/java/android/hardware/ConsumerIrManager.java
+++ b/core/java/android/hardware/ConsumerIrManager.java
@@ -60,8 +60,8 @@
try {
return mService.hasIrEmitter();
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
- return false;
}
/**
@@ -84,7 +84,7 @@
try {
mService.transmit(mPackageName, carrierFrequency, pattern);
} catch (RemoteException e) {
- Log.w(TAG, "failed to transmit.", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -149,8 +149,7 @@
}
return range;
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
- return null;
}
-
}
diff --git a/core/java/android/hardware/ICamera.aidl b/core/java/android/hardware/ICamera.aidl
deleted file mode 100644
index d4f64f8..0000000
--- a/core/java/android/hardware/ICamera.aidl
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (C) 2013 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 android.hardware;
-
-/** @hide */
-interface ICamera
-{
- /**
- * Keep up-to-date with frameworks/av/include/camera/ICamera.h
- */
- void disconnect();
-}
diff --git a/core/java/android/hardware/ICameraClient.aidl b/core/java/android/hardware/ICameraClient.aidl
deleted file mode 100644
index d7877b4..0000000
--- a/core/java/android/hardware/ICameraClient.aidl
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (C) 2013 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 android.hardware;
-
-/** @hide */
-interface ICameraClient
-{
- /**
- * Keep up-to-date with frameworks/av/include/camera/ICameraClient.h
- */
- // TODO: consider implementing this.
-}
diff --git a/core/java/android/hardware/ICameraService.aidl b/core/java/android/hardware/ICameraService.aidl
deleted file mode 100644
index 0b165cd..0000000
--- a/core/java/android/hardware/ICameraService.aidl
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright (C) 2013 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 android.hardware;
-
-import android.hardware.ICamera;
-import android.hardware.ICameraClient;
-import android.hardware.camera2.ICameraDeviceUser;
-import android.hardware.camera2.ICameraDeviceCallbacks;
-import android.hardware.camera2.impl.CameraMetadataNative;
-import android.hardware.camera2.utils.BinderHolder;
-import android.hardware.ICameraServiceListener;
-import android.hardware.CameraInfo;
-
-/**
- * Binder interface for the native camera service running in mediaserver.
- *
- * @hide
- */
-interface ICameraService
-{
- /**
- * Keep up-to-date with frameworks/av/include/camera/ICameraService.h
- */
- int getNumberOfCameras(int type);
-
- // rest of 'int' return values in this file are actually status_t
-
- int getCameraInfo(int cameraId, out CameraInfo info);
-
- int connect(ICameraClient client, int cameraId,
- String opPackageName,
- int clientUid,
- // Container for an ICamera object
- out BinderHolder device);
-
- int connectDevice(ICameraDeviceCallbacks callbacks, int cameraId,
- String opPackageName,
- int clientUid,
- // Container for an ICameraDeviceUser object
- out BinderHolder device);
-
- int addListener(ICameraServiceListener listener);
- int removeListener(ICameraServiceListener listener);
-
- int getCameraCharacteristics(int cameraId, out CameraMetadataNative info);
-
- /**
- * The java stubs for this method are not intended to be used. Please use
- * the native stub in frameworks/av/include/camera/ICameraService.h instead.
- * The BinderHolder output is being used as a placeholder, and will not be
- * well-formatted in the generated java method.
- */
- int getCameraVendorTagDescriptor(out BinderHolder desc);
-
- // Writes the camera1 parameters into a single-element array.
- int getLegacyParameters(int cameraId, out String[] parameters);
- // Determines if a particular API version is supported; see ICameraService.h for version defines
- int supportsCameraApi(int cameraId, int apiVersion);
-
- int connectLegacy(ICameraClient client, int cameraId,
- int halVersion,
- String opPackageName,
- int clientUid,
- // Container for an ICamera object
- out BinderHolder device);
-
- int setTorchMode(String CameraId, boolean enabled, IBinder clientBinder);
-
- /**
- * Notify the camera service of a system event. Should only be called from system_server.
- *
- * Callers require the android.permission.CAMERA_SEND_SYSTEM_EVENTS permission.
- */
- oneway void notifySystemEvent(int eventId, in int[] args);
-}
diff --git a/core/java/android/hardware/ICameraServiceProxy.aidl b/core/java/android/hardware/ICameraServiceProxy.aidl
deleted file mode 100644
index 0e654d5..0000000
--- a/core/java/android/hardware/ICameraServiceProxy.aidl
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2015 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 android.hardware;
-
-/**
- * Binder interface for the camera service proxy running in system_server.
- *
- * Keep in sync with frameworks/av/include/camera/ICameraServiceProxy.h
- *
- * @hide
- */
-interface ICameraServiceProxy
-{
- /**
- * Ping the service proxy to update the valid users for the camera service.
- */
- oneway void pingForUserUpdate();
-
- /**
- * Update the status of a camera device
- */
- oneway void notifyCameraState(String cameraId, int newCameraState);
-}
diff --git a/core/java/android/hardware/SensorEventListener.java b/core/java/android/hardware/SensorEventListener.java
index 0d859fb..0c059ba 100644
--- a/core/java/android/hardware/SensorEventListener.java
+++ b/core/java/android/hardware/SensorEventListener.java
@@ -18,28 +18,33 @@
/**
* Used for receiving notifications from the SensorManager when
- * sensor values have changed.
+ * there is new sensor data.
*/
public interface SensorEventListener {
/**
- * Called when sensor values have changed.
+ * Called when there is a new sensor event. Note that "on changed"
+ * is somewhat of a misnomer, as this will also be called if we have a
+ * new reading from a sensor with the exact same sensor values (but a
+ * newer timestamp).
+ *
* <p>See {@link android.hardware.SensorManager SensorManager}
* for details on possible sensor types.
* <p>See also {@link android.hardware.SensorEvent SensorEvent}.
- *
+ *
* <p><b>NOTE:</b> The application doesn't own the
* {@link android.hardware.SensorEvent event}
* object passed as a parameter and therefore cannot hold on to it.
* The object may be part of an internal pool and may be reused by
* the framework.
*
- * @param event the {@link android.hardware.SensorEvent SensorEvent}.
+ * @param event the {@link android.hardware.SensorEvent SensorEvent}.
*/
public void onSensorChanged(SensorEvent event);
/**
- * Called when the accuracy of the registered sensor has changed.
+ * Called when the accuracy of the registered sensor has changed. Unlike
+ * onSensorChanged(), this is only called when this accuracy value changes.
*
* <p>See the SENSOR_STATUS_* constants in
* {@link android.hardware.SensorManager SensorManager} for details.
diff --git a/core/java/android/hardware/SensorManager.java b/core/java/android/hardware/SensorManager.java
index f0b17c30..5684aa5 100644
--- a/core/java/android/hardware/SensorManager.java
+++ b/core/java/android/hardware/SensorManager.java
@@ -46,7 +46,7 @@
* is an example of a trigger sensor.
* </p>
* <pre class="prettyprint">
- * public class SensorActivity extends Activity, implements SensorEventListener {
+ * public class SensorActivity extends Activity implements SensorEventListener {
* private final SensorManager mSensorManager;
* private final Sensor mAccelerometer;
*
diff --git a/core/java/android/hardware/SerialManager.java b/core/java/android/hardware/SerialManager.java
index e0680bf22..83f7649 100644
--- a/core/java/android/hardware/SerialManager.java
+++ b/core/java/android/hardware/SerialManager.java
@@ -14,13 +14,11 @@
* limitations under the License.
*/
-
package android.hardware;
import android.content.Context;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
-import android.util.Log;
import java.io.IOException;
@@ -50,8 +48,7 @@
try {
return mService.getSerialPorts();
} catch (RemoteException e) {
- Log.e(TAG, "RemoteException in getSerialPorts", e);
- return null;
+ throw e.rethrowFromSystemServer();
}
}
@@ -77,8 +74,7 @@
throw new IOException("Could not open serial port " + name);
}
} catch (RemoteException e) {
- Log.e(TAG, "exception in UsbManager.openDevice", e);
+ throw e.rethrowFromSystemServer();
}
- return null;
}
}
diff --git a/core/java/android/hardware/camera2/CameraAccessException.java b/core/java/android/hardware/camera2/CameraAccessException.java
index 933ce0d..f9b659c 100644
--- a/core/java/android/hardware/camera2/CameraAccessException.java
+++ b/core/java/android/hardware/camera2/CameraAccessException.java
@@ -114,12 +114,12 @@
}
public CameraAccessException(@AccessError int problem, String message) {
- super(message);
+ super(getCombinedMessage(problem, message));
mReason = problem;
}
public CameraAccessException(@AccessError int problem, String message, Throwable cause) {
- super(message, cause);
+ super(getCombinedMessage(problem, message), cause);
mReason = problem;
}
@@ -151,4 +151,37 @@
}
return null;
}
+
+ private static String getCombinedMessage(@AccessError int problem, String message) {
+ String problemString = getProblemString(problem);
+ return String.format("%s (%d): %s", problemString, problem, message);
+ }
+
+ private static String getProblemString(int problem) {
+ String problemString;
+ switch (problem) {
+ case CAMERA_IN_USE:
+ problemString = "CAMERA_IN_USE";
+ break;
+ case MAX_CAMERAS_IN_USE:
+ problemString = "MAX_CAMERAS_IN_USE";
+ break;
+ case CAMERA_DISCONNECTED:
+ problemString = "CAMERA_DISCONNECTED";
+ break;
+ case CAMERA_DISABLED:
+ problemString = "CAMERA_DISABLED";
+ break;
+ case CAMERA_ERROR:
+ problemString = "CAMERA_ERROR";
+ break;
+ case CAMERA_DEPRECATED_HAL:
+ problemString = "CAMERA_DEPRECATED_HAL";
+ break;
+ default:
+ problemString = "<UNKNOWN ERROR>";
+ }
+ return problemString;
+ }
+
}
diff --git a/core/java/android/hardware/camera2/CameraManager.java b/core/java/android/hardware/camera2/CameraManager.java
index 51796eb..b3c8e3b 100644
--- a/core/java/android/hardware/camera2/CameraManager.java
+++ b/core/java/android/hardware/camera2/CameraManager.java
@@ -26,15 +26,14 @@
import android.hardware.camera2.impl.CameraMetadataNative;
import android.hardware.camera2.legacy.CameraDeviceUserShim;
import android.hardware.camera2.legacy.LegacyMetadataMapper;
-import android.hardware.camera2.utils.CameraServiceBinderDecorator;
-import android.hardware.camera2.utils.CameraRuntimeException;
-import android.hardware.camera2.utils.BinderHolder;
import android.os.IBinder;
import android.os.Binder;
+import android.os.DeadObjectException;
import android.os.Handler;
import android.os.Looper;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.os.ServiceSpecificException;
import android.util.Log;
import android.util.ArrayMap;
@@ -240,25 +239,19 @@
if (!supportsCamera2ApiLocked(cameraId)) {
// Legacy backwards compatibility path; build static info from the camera
// parameters
- String[] outParameters = new String[1];
+ String parameters = cameraService.getLegacyParameters(id);
- cameraService.getLegacyParameters(id, /*out*/outParameters);
- String parameters = outParameters[0];
-
- CameraInfo info = new CameraInfo();
- cameraService.getCameraInfo(id, /*out*/info);
+ CameraInfo info = cameraService.getCameraInfo(id);
characteristics = LegacyMetadataMapper.createCharacteristics(parameters, info);
} else {
// Normal path: Get the camera characteristics directly from the camera service
- CameraMetadataNative info = new CameraMetadataNative();
-
- cameraService.getCameraCharacteristics(id, info);
+ CameraMetadataNative info = cameraService.getCameraCharacteristics(id);
characteristics = new CameraCharacteristics(info);
}
- } catch (CameraRuntimeException e) {
- throw e.asChecked();
+ } catch (ServiceSpecificException e) {
+ throwAsPublicException(e);
} catch (RemoteException e) {
// Camera service died - act as if the camera was disconnected
throw new CameraAccessException(CameraAccessException.CAMERA_DISCONNECTED,
@@ -292,85 +285,83 @@
throws CameraAccessException {
CameraCharacteristics characteristics = getCameraCharacteristics(cameraId);
CameraDevice device = null;
- try {
- synchronized (mLock) {
+ synchronized (mLock) {
- ICameraDeviceUser cameraUser = null;
+ ICameraDeviceUser cameraUser = null;
- android.hardware.camera2.impl.CameraDeviceImpl deviceImpl =
- new android.hardware.camera2.impl.CameraDeviceImpl(
- cameraId,
- callback,
- handler,
- characteristics);
+ android.hardware.camera2.impl.CameraDeviceImpl deviceImpl =
+ new android.hardware.camera2.impl.CameraDeviceImpl(
+ cameraId,
+ callback,
+ handler,
+ characteristics);
- BinderHolder holder = new BinderHolder();
+ ICameraDeviceCallbacks callbacks = deviceImpl.getCallbacks();
- ICameraDeviceCallbacks callbacks = deviceImpl.getCallbacks();
- int id = Integer.parseInt(cameraId);
- try {
- if (supportsCamera2ApiLocked(cameraId)) {
- // Use cameraservice's cameradeviceclient implementation for HAL3.2+ devices
- ICameraService cameraService = CameraManagerGlobal.get().getCameraService();
- if (cameraService == null) {
- throw new CameraRuntimeException(
- CameraAccessException.CAMERA_DISCONNECTED,
- "Camera service is currently unavailable");
- }
- cameraService.connectDevice(callbacks, id,
- mContext.getOpPackageName(), USE_CALLING_UID, holder);
- cameraUser = ICameraDeviceUser.Stub.asInterface(holder.getBinder());
- } else {
- // Use legacy camera implementation for HAL1 devices
- Log.i(TAG, "Using legacy camera HAL.");
- cameraUser = CameraDeviceUserShim.connectBinderShim(callbacks, id);
- }
- } catch (CameraRuntimeException e) {
- if (e.getReason() == CameraAccessException.CAMERA_DEPRECATED_HAL) {
- throw new AssertionError("Should've gone down the shim path");
- } else if (e.getReason() == CameraAccessException.CAMERA_IN_USE ||
- e.getReason() == CameraAccessException.MAX_CAMERAS_IN_USE ||
- e.getReason() == CameraAccessException.CAMERA_DISABLED ||
- e.getReason() == CameraAccessException.CAMERA_DISCONNECTED ||
- e.getReason() == CameraAccessException.CAMERA_ERROR) {
- // Received one of the known connection errors
- // The remote camera device cannot be connected to, so
- // set the local camera to the startup error state
- deviceImpl.setRemoteFailure(e);
-
- if (e.getReason() == CameraAccessException.CAMERA_DISABLED ||
- e.getReason() == CameraAccessException.CAMERA_DISCONNECTED ||
- e.getReason() == CameraAccessException.CAMERA_IN_USE) {
- // Per API docs, these failures call onError and throw
- throw e.asChecked();
- }
- } else {
- // Unexpected failure - rethrow
- throw e;
- }
- } catch (RemoteException e) {
- // Camera service died - act as if it's a CAMERA_DISCONNECTED case
- CameraRuntimeException ce = new CameraRuntimeException(
- CameraAccessException.CAMERA_DISCONNECTED,
- "Camera service is currently unavailable", e);
- deviceImpl.setRemoteFailure(ce);
- throw ce.asChecked();
- }
-
- // TODO: factor out callback to be non-nested, then move setter to constructor
- // For now, calling setRemoteDevice will fire initial
- // onOpened/onUnconfigured callbacks.
- deviceImpl.setRemoteDevice(cameraUser);
- device = deviceImpl;
+ int id;
+ try {
+ id = Integer.parseInt(cameraId);
+ } catch (NumberFormatException e) {
+ throw new IllegalArgumentException("Expected cameraId to be numeric, but it was: "
+ + cameraId);
}
- } catch (NumberFormatException e) {
- throw new IllegalArgumentException("Expected cameraId to be numeric, but it was: "
- + cameraId);
- } catch (CameraRuntimeException e) {
- throw e.asChecked();
+ try {
+ if (supportsCamera2ApiLocked(cameraId)) {
+ // Use cameraservice's cameradeviceclient implementation for HAL3.2+ devices
+ ICameraService cameraService = CameraManagerGlobal.get().getCameraService();
+ if (cameraService == null) {
+ throw new ServiceSpecificException(
+ ICameraService.ERROR_DISCONNECTED,
+ "Camera service is currently unavailable");
+ }
+ cameraUser = cameraService.connectDevice(callbacks, id,
+ mContext.getOpPackageName(), USE_CALLING_UID);
+ } else {
+ // Use legacy camera implementation for HAL1 devices
+ Log.i(TAG, "Using legacy camera HAL.");
+ cameraUser = CameraDeviceUserShim.connectBinderShim(callbacks, id);
+ }
+ } catch (ServiceSpecificException e) {
+ if (e.errorCode == ICameraService.ERROR_DEPRECATED_HAL) {
+ throw new AssertionError("Should've gone down the shim path");
+ } else if (e.errorCode == ICameraService.ERROR_CAMERA_IN_USE ||
+ e.errorCode == ICameraService.ERROR_MAX_CAMERAS_IN_USE ||
+ e.errorCode == ICameraService.ERROR_DISABLED ||
+ e.errorCode == ICameraService.ERROR_DISCONNECTED ||
+ e.errorCode == ICameraService.ERROR_INVALID_OPERATION) {
+ // Received one of the known connection errors
+ // The remote camera device cannot be connected to, so
+ // set the local camera to the startup error state
+ deviceImpl.setRemoteFailure(e);
+
+ if (e.errorCode == ICameraService.ERROR_DISABLED ||
+ e.errorCode == ICameraService.ERROR_DISCONNECTED ||
+ e.errorCode == ICameraService.ERROR_CAMERA_IN_USE) {
+ // Per API docs, these failures call onError and throw
+ throwAsPublicException(e);
+ }
+ } else {
+ // Unexpected failure - rethrow
+ throwAsPublicException(e);
+ }
+ } catch (RemoteException e) {
+ // Camera service died - act as if it's a CAMERA_DISCONNECTED case
+ ServiceSpecificException sse = new ServiceSpecificException(
+ ICameraService.ERROR_DISCONNECTED,
+ "Camera service is currently unavailable");
+ deviceImpl.setRemoteFailure(sse);
+ throwAsPublicException(sse);
+ }
+
+ // TODO: factor out callback to be non-nested, then move setter to constructor
+ // For now, calling setRemoteDevice will fire initial
+ // onOpened/onUnconfigured callbacks.
+ deviceImpl.setRemoteDevice(cameraUser);
+ device = deviceImpl;
}
+
return device;
}
@@ -602,6 +593,56 @@
}
/**
+ * Convert ServiceSpecificExceptions and Binder RemoteExceptions from camera binder interfaces
+ * into the correct public exceptions.
+ *
+ * @hide
+ */
+ public static void throwAsPublicException(Throwable t) throws CameraAccessException {
+ if (t instanceof ServiceSpecificException) {
+ ServiceSpecificException e = (ServiceSpecificException) t;
+ int reason = CameraAccessException.CAMERA_ERROR;
+ switch(e.errorCode) {
+ case ICameraService.ERROR_DISCONNECTED:
+ reason = CameraAccessException.CAMERA_DISCONNECTED;
+ break;
+ case ICameraService.ERROR_DISABLED:
+ reason = CameraAccessException.CAMERA_DISABLED;
+ break;
+ case ICameraService.ERROR_CAMERA_IN_USE:
+ reason = CameraAccessException.CAMERA_IN_USE;
+ break;
+ case ICameraService.ERROR_MAX_CAMERAS_IN_USE:
+ reason = CameraAccessException.MAX_CAMERAS_IN_USE;
+ break;
+ case ICameraService.ERROR_DEPRECATED_HAL:
+ reason = CameraAccessException.CAMERA_DEPRECATED_HAL;
+ break;
+ case ICameraService.ERROR_ILLEGAL_ARGUMENT:
+ case ICameraService.ERROR_ALREADY_EXISTS:
+ throw new IllegalArgumentException(e.getMessage(), e);
+ case ICameraService.ERROR_PERMISSION_DENIED:
+ throw new SecurityException(e.getMessage(), e);
+ case ICameraService.ERROR_TIMED_OUT:
+ case ICameraService.ERROR_INVALID_OPERATION:
+ default:
+ reason = CameraAccessException.CAMERA_ERROR;
+ }
+ throw new CameraAccessException(reason, e.getMessage(), e);
+ } else if (t instanceof DeadObjectException) {
+ throw new CameraAccessException(CameraAccessException.CAMERA_DISCONNECTED,
+ "Camera service has died unexpectedly",
+ t);
+ } else if (t instanceof RemoteException) {
+ throw new UnsupportedOperationException("An unknown RemoteException was thrown" +
+ " which should never happen.", t);
+ } else if (t instanceof RuntimeException) {
+ RuntimeException e = (RuntimeException) t;
+ throw e;
+ }
+ }
+
+ /**
* Return or create the list of currently connected camera devices.
*
* <p>In case of errors connecting to the camera service, will return an empty list.</p>
@@ -619,34 +660,32 @@
try {
numCameras = cameraService.getNumberOfCameras(CAMERA_TYPE_ALL);
- } catch(CameraRuntimeException e) {
- throw e.asChecked();
+ } catch(ServiceSpecificException e) {
+ throwAsPublicException(e);
} catch (RemoteException e) {
// camera service just died - if no camera service, then no devices
return deviceIdList;
}
- CameraMetadataNative info = new CameraMetadataNative();
for (int i = 0; i < numCameras; ++i) {
// Non-removable cameras use integers starting at 0 for their
// identifiers
boolean isDeviceSupported = false;
try {
- cameraService.getCameraCharacteristics(i, info);
+ CameraMetadataNative info = cameraService.getCameraCharacteristics(i);
if (!info.isEmpty()) {
isDeviceSupported = true;
} else {
throw new AssertionError("Expected to get non-empty characteristics");
}
- } catch(IllegalArgumentException e) {
- // Got a BAD_VALUE from service, meaning that this
- // device is not supported.
- } catch(CameraRuntimeException e) {
+ } catch(ServiceSpecificException e) {
// DISCONNECTED means that the HAL reported an low-level error getting the
- // device info; skip listing the device. Other errors,
+ // device info; ILLEGAL_ARGUMENT means that this devices is not supported.
+ // Skip listing the device. Other errors,
// propagate exception onward
- if (e.getReason() != CameraAccessException.CAMERA_DISCONNECTED) {
- throw e.asChecked();
+ if (e.errorCode != ICameraService.ERROR_DISCONNECTED ||
+ e.errorCode != ICameraService.ERROR_ILLEGAL_ARGUMENT) {
+ throwAsPublicException(e);
}
} catch(RemoteException e) {
// Camera service died - no devices to list
@@ -699,17 +738,7 @@
// If no camera service, no support
if (cameraService == null) return false;
- int res = cameraService.supportsCameraApi(id, apiVersion);
-
- if (res != CameraServiceBinderDecorator.NO_ERROR) {
- throw new AssertionError("Unexpected value " + res);
- }
- return true;
- } catch (CameraRuntimeException e) {
- if (e.getReason() != CameraAccessException.CAMERA_DEPRECATED_HAL) {
- throw e;
- }
- // API level is not supported
+ return cameraService.supportsCameraApi(id, apiVersion);
} catch (RemoteException e) {
// Camera service is now down, no support for any API level
}
@@ -737,21 +766,6 @@
*/
private static final String CAMERA_SERVICE_BINDER_NAME = "media.camera";
- // Keep up-to-date with ICameraServiceListener.h
-
- // Device physically unplugged
- public static final int STATUS_NOT_PRESENT = 0;
- // Device physically has been plugged in
- // and the camera can be used exclusively
- public static final int STATUS_PRESENT = 1;
- // Device physically has been plugged in
- // but it will not be connect-able until enumeration is complete
- public static final int STATUS_ENUMERATING = 2;
- // Camera is in use by another app and cannot be used exclusively
- public static final int STATUS_NOT_AVAILABLE = 0x80000000;
-
- // End enums shared with ICameraServiceListener.h
-
// Camera ID -> Status map
private final ArrayMap<String, Integer> mDeviceStatus = new ArrayMap<String, Integer>();
@@ -759,17 +773,6 @@
private final ArrayMap<AvailabilityCallback, Handler> mCallbackMap =
new ArrayMap<AvailabilityCallback, Handler>();
- // Keep up-to-date with ICameraServiceListener.h
-
- // torch mode has become not available to set via setTorchMode().
- public static final int TORCH_STATUS_NOT_AVAILABLE = 0;
- // torch mode is off and available to be turned on via setTorchMode().
- public static final int TORCH_STATUS_AVAILABLE_OFF = 1;
- // torch mode is on and available to be turned off via setTorchMode().
- public static final int TORCH_STATUS_AVAILABLE_ON = 2;
-
- // End enums shared with ICameraServiceListener.h
-
// torch client binder to set the torch mode with.
private Binder mTorchClientBinder = new Binder();
@@ -839,29 +842,20 @@
return;
}
- ICameraService cameraServiceRaw = ICameraService.Stub.asInterface(cameraServiceBinder);
-
- /**
- * Wrap the camera service in a decorator which automatically translates return codes
- * into exceptions.
- */
- ICameraService cameraService =
- CameraServiceBinderDecorator.newInstance(cameraServiceRaw);
+ ICameraService cameraService = ICameraService.Stub.asInterface(cameraServiceBinder);
try {
- CameraServiceBinderDecorator.throwOnError(
- CameraMetadataNative.nativeSetupGlobalVendorTagDescriptor());
- } catch (CameraRuntimeException e) {
- handleRecoverableSetupErrors(e, "Failed to set up vendor tags");
+ CameraMetadataNative.setupGlobalVendorTagDescriptor();
+ } catch (ServiceSpecificException e) {
+ handleRecoverableSetupErrors(e);
}
try {
cameraService.addListener(this);
mCameraService = cameraService;
- } catch(CameraRuntimeException e) {
+ } catch(ServiceSpecificException e) {
// Unexpected failure
- throw new IllegalStateException("Failed to register a camera service listener",
- e.asChecked());
+ throw new IllegalStateException("Failed to register a camera service listener", e);
} catch (RemoteException e) {
// Camera service is now down, leave mCameraService as null
}
@@ -881,16 +875,9 @@
}
try {
- int status = cameraService.setTorchMode(cameraId, enabled, mTorchClientBinder);
- } catch(CameraRuntimeException e) {
- int problem = e.getReason();
- switch (problem) {
- case CameraAccessException.CAMERA_ERROR:
- throw new IllegalArgumentException(
- "the camera device doesn't have a flash unit.");
- default:
- throw e.asChecked();
- }
+ cameraService.setTorchMode(cameraId, enabled, mTorchClientBinder);
+ } catch(ServiceSpecificException e) {
+ throwAsPublicException(e);
} catch (RemoteException e) {
throw new CameraAccessException(CameraAccessException.CAMERA_DISCONNECTED,
"Camera service is currently unavailable");
@@ -898,21 +885,19 @@
}
}
- private void handleRecoverableSetupErrors(CameraRuntimeException e, String msg) {
- int problem = e.getReason();
- switch (problem) {
- case CameraAccessException.CAMERA_DISCONNECTED:
- String errorMsg = CameraAccessException.getDefaultMessage(problem);
- Log.w(TAG, msg + ": " + errorMsg);
+ private void handleRecoverableSetupErrors(ServiceSpecificException e) {
+ switch (e.errorCode) {
+ case ICameraService.ERROR_DISCONNECTED:
+ Log.w(TAG, e.getMessage());
break;
default:
- throw new IllegalStateException(msg, e.asChecked());
+ throw new IllegalStateException(e);
}
}
private boolean isAvailable(int status) {
switch (status) {
- case STATUS_PRESENT:
+ case ICameraServiceListener.STATUS_PRESENT:
return true;
default:
return false;
@@ -921,10 +906,10 @@
private boolean validStatus(int status) {
switch (status) {
- case STATUS_NOT_PRESENT:
- case STATUS_PRESENT:
- case STATUS_ENUMERATING:
- case STATUS_NOT_AVAILABLE:
+ case ICameraServiceListener.STATUS_NOT_PRESENT:
+ case ICameraServiceListener.STATUS_PRESENT:
+ case ICameraServiceListener.STATUS_ENUMERATING:
+ case ICameraServiceListener.STATUS_NOT_AVAILABLE:
return true;
default:
return false;
@@ -933,9 +918,9 @@
private boolean validTorchStatus(int status) {
switch (status) {
- case TORCH_STATUS_NOT_AVAILABLE:
- case TORCH_STATUS_AVAILABLE_ON:
- case TORCH_STATUS_AVAILABLE_OFF:
+ case ICameraServiceListener.TORCH_STATUS_NOT_AVAILABLE:
+ case ICameraServiceListener.TORCH_STATUS_AVAILABLE_ON:
+ case ICameraServiceListener.TORCH_STATUS_AVAILABLE_OFF:
return true;
default:
return false;
@@ -966,14 +951,14 @@
private void postSingleTorchUpdate(final TorchCallback callback, final Handler handler,
final String id, final int status) {
switch(status) {
- case TORCH_STATUS_AVAILABLE_ON:
- case TORCH_STATUS_AVAILABLE_OFF:
+ case ICameraServiceListener.TORCH_STATUS_AVAILABLE_ON:
+ case ICameraServiceListener.TORCH_STATUS_AVAILABLE_OFF:
handler.post(
new Runnable() {
@Override
public void run() {
callback.onTorchModeChanged(id, status ==
- TORCH_STATUS_AVAILABLE_ON);
+ ICameraServiceListener.TORCH_STATUS_AVAILABLE_ON);
}
});
break;
@@ -1220,11 +1205,12 @@
// and torch statuses will be updated.
for (int i = 0; i < mDeviceStatus.size(); i++) {
String cameraId = mDeviceStatus.keyAt(i);
- onStatusChangedLocked(STATUS_NOT_PRESENT, cameraId);
+ onStatusChangedLocked(ICameraServiceListener.STATUS_NOT_PRESENT, cameraId);
}
for (int i = 0; i < mTorchStatus.size(); i++) {
String cameraId = mTorchStatus.keyAt(i);
- onTorchStatusChangedLocked(TORCH_STATUS_NOT_AVAILABLE, cameraId);
+ onTorchStatusChangedLocked(ICameraServiceListener.TORCH_STATUS_NOT_AVAILABLE,
+ cameraId);
}
scheduleCameraServiceReconnectionLocked();
diff --git a/core/java/android/hardware/camera2/CaptureRequest.aidl b/core/java/android/hardware/camera2/CaptureRequest.aidl
deleted file mode 100644
index 0b7d5ba..0000000
--- a/core/java/android/hardware/camera2/CaptureRequest.aidl
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright (C) 2013 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 android.hardware.camera2;
-
-/** @hide */
-parcelable CaptureRequest;
diff --git a/core/java/android/hardware/camera2/ICameraDeviceCallbacks.aidl b/core/java/android/hardware/camera2/ICameraDeviceCallbacks.aidl
deleted file mode 100644
index 151c918..0000000
--- a/core/java/android/hardware/camera2/ICameraDeviceCallbacks.aidl
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2013 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 android.hardware.camera2;
-
-import android.hardware.camera2.impl.CameraMetadataNative;
-import android.hardware.camera2.impl.CaptureResultExtras;
-
-/** @hide */
-interface ICameraDeviceCallbacks
-{
- /**
- * Keep up-to-date with frameworks/av/include/camera/camera2/ICameraDeviceCallbacks.h
- */
-
- oneway void onDeviceError(int errorCode, in CaptureResultExtras resultExtras);
- oneway void onDeviceIdle();
- oneway void onCaptureStarted(in CaptureResultExtras resultExtras, long timestamp);
- oneway void onResultReceived(in CameraMetadataNative result,
- in CaptureResultExtras resultExtras);
- oneway void onPrepared(int streamId);
-}
diff --git a/core/java/android/hardware/camera2/ICameraDeviceUser.aidl b/core/java/android/hardware/camera2/ICameraDeviceUser.aidl
deleted file mode 100644
index c9c9abc..0000000
--- a/core/java/android/hardware/camera2/ICameraDeviceUser.aidl
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Copyright (C) 2013 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 android.hardware.camera2;
-
-import android.hardware.camera2.CaptureRequest;
-import android.hardware.camera2.impl.CameraMetadataNative;
-import android.hardware.camera2.params.OutputConfiguration;
-import android.hardware.camera2.utils.LongParcelable;
-import android.view.Surface;
-
-/** @hide */
-interface ICameraDeviceUser
-{
- /**
- * Keep up-to-date with frameworks/av/include/camera/camera2/ICameraDeviceUser.h and
- * frameworks/base/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java
- */
- void disconnect();
-
- // ints here are status_t
-
- // non-negative value is the requestId. negative value is status_t
- int submitRequest(in CaptureRequest request, boolean streaming,
- out LongParcelable lastFrameNumber);
-
- int submitRequestList(in List<CaptureRequest> requestList, boolean streaming,
- out LongParcelable lastFrameNumber);
-
- int cancelRequest(int requestId, out LongParcelable lastFrameNumber);
-
- /**
- * Begin the device configuration.
- *
- * <p>
- * beginConfigure must be called before any call to deleteStream, createStream,
- * or endConfigure. It is not valid to call this when the device is not idle.
- * <p>
- */
- int beginConfigure();
-
- /**
- * End the device configuration.
- *
- * <p>
- * endConfigure must be called after stream configuration is complete (i.e. after
- * a call to beginConfigure and subsequent createStream/deleteStream calls). This
- * must be called before any requests can be submitted.
- * <p>
- */
- int endConfigure(boolean isConstrainedHighSpeed);
-
- int deleteStream(int streamId);
-
- // non-negative value is the stream ID. negative value is status_t
- int createStream(in OutputConfiguration outputConfiguration);
-
- /**
- * Create an input stream
- *
- * <p>Create an input stream of width, height, and format</p>
- *
- * @param width Width of the input buffers
- * @param height Height of the input buffers
- * @param format Format of the input buffers. One of HAL_PIXEL_FORMAT_*.
- *
- * @return stream ID if it's a non-negative value. status_t if it's a negative value.
- */
- int createInputStream(int width, int height, int format);
-
- /**
- * Get the surface of the input stream.
- *
- * <p>It's valid to call this method only after a stream configuration is completed
- * successfully and the stream configuration includes a input stream.</p>
- *
- * @param surface An output argument for the surface of the input stream buffer queue.
- */
- int getInputSurface(out Surface surface);
-
- int createDefaultRequest(int templateId, out CameraMetadataNative request);
-
- int getCameraInfo(out CameraMetadataNative info);
-
- int waitUntilIdle();
-
- int flush(out LongParcelable lastFrameNumber);
-
- int prepare(int streamId);
-
- int tearDown(int streamId);
-
- int prepare2(int maxCount, int streamId);
-}
diff --git a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
index 3aba0d1..00dd780 100644
--- a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
+++ b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
@@ -33,14 +33,14 @@
import android.hardware.camera2.params.OutputConfiguration;
import android.hardware.camera2.params.ReprocessFormatsMap;
import android.hardware.camera2.params.StreamConfigurationMap;
-import android.hardware.camera2.utils.CameraBinderDecorator;
-import android.hardware.camera2.utils.CameraRuntimeException;
-import android.hardware.camera2.utils.LongParcelable;
+import android.hardware.camera2.utils.SubmitInfo;
import android.hardware.camera2.utils.SurfaceUtils;
+import android.hardware.ICameraService;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.RemoteException;
+import android.os.ServiceSpecificException;
import android.util.Log;
import android.util.Range;
import android.util.Size;
@@ -70,7 +70,7 @@
private static final int REQUEST_ID_NONE = -1;
// TODO: guard every function with if (!mRemoteDevice) check (if it was closed)
- private ICameraDeviceUser mRemoteDevice;
+ private ICameraDeviceUserWrapper mRemoteDevice;
// Lock to synchronize cross-thread access to device public interface
final Object mInterfaceLock = new Object(); // access from this class and Session only!
@@ -267,7 +267,7 @@
// If setRemoteFailure already called, do nothing
if (mInError) return;
- mRemoteDevice = CameraBinderDecorator.newInstance(remoteDevice);
+ mRemoteDevice = new ICameraDeviceUserWrapper(remoteDevice);
mDeviceHandler.post(mCallOnOpened);
mDeviceHandler.post(mCallOnUnconfigured);
@@ -280,28 +280,29 @@
* <p>This places the camera device in the error state and informs the callback.
* Use in place of setRemoteDevice() when startup fails.</p>
*/
- public void setRemoteFailure(final CameraRuntimeException failure) {
+ public void setRemoteFailure(final ServiceSpecificException failure) {
int failureCode = StateCallback.ERROR_CAMERA_DEVICE;
boolean failureIsError = true;
- switch (failure.getReason()) {
- case CameraAccessException.CAMERA_IN_USE:
+ switch (failure.errorCode) {
+ case ICameraService.ERROR_CAMERA_IN_USE:
failureCode = StateCallback.ERROR_CAMERA_IN_USE;
break;
- case CameraAccessException.MAX_CAMERAS_IN_USE:
+ case ICameraService.ERROR_MAX_CAMERAS_IN_USE:
failureCode = StateCallback.ERROR_MAX_CAMERAS_IN_USE;
break;
- case CameraAccessException.CAMERA_DISABLED:
+ case ICameraService.ERROR_DISABLED:
failureCode = StateCallback.ERROR_CAMERA_DISABLED;
break;
- case CameraAccessException.CAMERA_DISCONNECTED:
+ case ICameraService.ERROR_DISCONNECTED:
failureIsError = false;
break;
- case CameraAccessException.CAMERA_ERROR:
+ case ICameraService.ERROR_INVALID_OPERATION:
failureCode = StateCallback.ERROR_CAMERA_DEVICE;
break;
default:
- Log.wtf(TAG, "Unknown failure in opening camera device: " + failure.getReason());
+ Log.e(TAG, "Unexpected failure in opening camera device: " + failure.errorCode +
+ failure.getMessage());
break;
}
final int code = failureCode;
@@ -430,27 +431,20 @@
}
}
- try {
- mRemoteDevice.endConfigure(isConstrainedHighSpeed);
- }
- catch (IllegalArgumentException e) {
- // OK. camera service can reject stream config if it's not supported by HAL
- // This is only the result of a programmer misusing the camera2 api.
- Log.w(TAG, "Stream configuration failed");
- return false;
- }
+ mRemoteDevice.endConfigure(isConstrainedHighSpeed);
success = true;
- } catch (CameraRuntimeException e) {
- if (e.getReason() == CAMERA_IN_USE) {
- throw new IllegalStateException("The camera is currently busy." +
- " You must wait until the previous operation completes.");
- }
-
- throw e.asChecked();
- } catch (RemoteException e) {
- // impossible
+ } catch (IllegalArgumentException e) {
+ // OK. camera service can reject stream config if it's not supported by HAL
+ // This is only the result of a programmer misusing the camera2 api.
+ Log.w(TAG, "Stream configuration failed due to: " + e.getMessage());
return false;
+ } catch (CameraAccessException e) {
+ if (e.getReason() == CameraAccessException.CAMERA_IN_USE) {
+ throw new IllegalStateException("The camera is currently busy." +
+ " You must wait until the previous operation completes.", e);
+ }
+ throw e;
} finally {
if (success && outputs.size() > 0) {
mDeviceHandler.post(mCallOnIdle);
@@ -594,12 +588,7 @@
configureSuccess = configureStreamsChecked(inputConfig, outputConfigurations,
isConstrainedHighSpeed);
if (configureSuccess == true && inputConfig != null) {
- input = new Surface();
- try {
- mRemoteDevice.getInputSurface(/*out*/input);
- } catch (CameraRuntimeException e) {
- e.asChecked();
- }
+ input = mRemoteDevice.getInputSurface();
}
} catch (CameraAccessException e) {
configureSuccess = false;
@@ -608,9 +597,6 @@
if (DEBUG) {
Log.v(TAG, "createCaptureSession - failed with exception ", e);
}
- } catch (RemoteException e) {
- // impossible
- return;
}
List<Surface> outSurfaces = new ArrayList<>(outputConfigurations.size());
@@ -655,16 +641,9 @@
synchronized(mInterfaceLock) {
checkIfCameraClosedOrInError();
- CameraMetadataNative templatedRequest = new CameraMetadataNative();
+ CameraMetadataNative templatedRequest = null;
- try {
- mRemoteDevice.createDefaultRequest(templateType, /*out*/templatedRequest);
- } catch (CameraRuntimeException e) {
- throw e.asChecked();
- } catch (RemoteException e) {
- // impossible
- return null;
- }
+ templatedRequest = mRemoteDevice.createDefaultRequest(templateType);
CaptureRequest.Builder builder = new CaptureRequest.Builder(
templatedRequest, /*reprocess*/false, CameraCaptureSession.SESSION_ID_NONE);
@@ -701,14 +680,8 @@
if (streamId == -1) {
throw new IllegalArgumentException("Surface is not part of this session");
}
- try {
- mRemoteDevice.prepare(streamId);
- } catch (CameraRuntimeException e) {
- throw e.asChecked();
- } catch (RemoteException e) {
- // impossible
- return;
- }
+
+ mRemoteDevice.prepare(streamId);
}
}
@@ -728,14 +701,8 @@
if (streamId == -1) {
throw new IllegalArgumentException("Surface is not part of this session");
}
- try {
- mRemoteDevice.prepare2(maxCount, streamId);
- } catch (CameraRuntimeException e) {
- throw e.asChecked();
- } catch (RemoteException e) {
- // impossible
- return;
- }
+
+ mRemoteDevice.prepare2(maxCount, streamId);
}
}
@@ -753,14 +720,8 @@
if (streamId == -1) {
throw new IllegalArgumentException("Surface is not part of this session");
}
- try {
- mRemoteDevice.tearDown(streamId);
- } catch (CameraRuntimeException e) {
- throw e.asChecked();
- } catch (RemoteException e) {
- // impossible
- return;
- }
+
+ mRemoteDevice.tearDown(streamId);
}
}
@@ -875,45 +836,37 @@
synchronized(mInterfaceLock) {
checkIfCameraClosedOrInError();
- int requestId;
-
if (repeating) {
stopRepeating();
}
- LongParcelable lastFrameNumberRef = new LongParcelable();
- try {
- requestId = mRemoteDevice.submitRequestList(requestList, repeating,
- /*out*/lastFrameNumberRef);
- if (DEBUG) {
- Log.v(TAG, "last frame number " + lastFrameNumberRef.getNumber());
- }
- } catch (CameraRuntimeException e) {
- throw e.asChecked();
- } catch (RemoteException e) {
- // impossible
- return -1;
+ SubmitInfo requestInfo;
+
+ CaptureRequest[] requestArray = requestList.toArray(new CaptureRequest[requestList.size()]);
+ requestInfo = mRemoteDevice.submitRequestList(requestArray, repeating);
+ if (DEBUG) {
+ Log.v(TAG, "last frame number " + requestInfo.getLastFrameNumber());
}
if (callback != null) {
- mCaptureCallbackMap.put(requestId, new CaptureCallbackHolder(callback,
- requestList, handler, repeating, mNextSessionId - 1));
+ mCaptureCallbackMap.put(requestInfo.getRequestId(),
+ new CaptureCallbackHolder(
+ callback, requestList, handler, repeating, mNextSessionId - 1));
} else {
if (DEBUG) {
- Log.d(TAG, "Listen for request " + requestId + " is null");
+ Log.d(TAG, "Listen for request " + requestInfo.getRequestId() + " is null");
}
}
- long lastFrameNumber = lastFrameNumberRef.getNumber();
-
if (repeating) {
if (mRepeatingRequestId != REQUEST_ID_NONE) {
- checkEarlyTriggerSequenceComplete(mRepeatingRequestId, lastFrameNumber);
+ checkEarlyTriggerSequenceComplete(mRepeatingRequestId,
+ requestInfo.getLastFrameNumber());
}
- mRepeatingRequestId = requestId;
+ mRepeatingRequestId = requestInfo.getRequestId();
} else {
- mRequestLastFrameNumbersList.add(new RequestLastFrameNumbersHolder(requestList,
- requestId, lastFrameNumber));
+ mRequestLastFrameNumbersList.add(
+ new RequestLastFrameNumbersHolder(requestList, requestInfo));
}
if (mIdle) {
@@ -921,7 +874,7 @@
}
mIdle = false;
- return requestId;
+ return requestInfo.getRequestId();
}
}
@@ -949,19 +902,9 @@
int requestId = mRepeatingRequestId;
mRepeatingRequestId = REQUEST_ID_NONE;
- try {
- LongParcelable lastFrameNumberRef = new LongParcelable();
- mRemoteDevice.cancelRequest(requestId, /*out*/lastFrameNumberRef);
- long lastFrameNumber = lastFrameNumberRef.getNumber();
+ long lastFrameNumber = mRemoteDevice.cancelRequest(requestId);
- checkEarlyTriggerSequenceComplete(requestId, lastFrameNumber);
-
- } catch (CameraRuntimeException e) {
- throw e.asChecked();
- } catch (RemoteException e) {
- // impossible
- return;
- }
+ checkEarlyTriggerSequenceComplete(requestId, lastFrameNumber);
}
}
}
@@ -974,14 +917,8 @@
if (mRepeatingRequestId != REQUEST_ID_NONE) {
throw new IllegalStateException("Active repeating request ongoing");
}
- try {
- mRemoteDevice.waitUntilIdle();
- } catch (CameraRuntimeException e) {
- throw e.asChecked();
- } catch (RemoteException e) {
- // impossible
- return;
- }
+
+ mRemoteDevice.waitUntilIdle();
}
}
@@ -997,19 +934,11 @@
mDeviceHandler.post(mCallOnIdle);
return;
}
- try {
- LongParcelable lastFrameNumberRef = new LongParcelable();
- mRemoteDevice.flush(/*out*/lastFrameNumberRef);
- if (mRepeatingRequestId != REQUEST_ID_NONE) {
- long lastFrameNumber = lastFrameNumberRef.getNumber();
- checkEarlyTriggerSequenceComplete(mRepeatingRequestId, lastFrameNumber);
- mRepeatingRequestId = REQUEST_ID_NONE;
- }
- } catch (CameraRuntimeException e) {
- throw e.asChecked();
- } catch (RemoteException e) {
- // impossible
- return;
+
+ long lastFrameNumber = mRemoteDevice.flush();
+ if (mRepeatingRequestId != REQUEST_ID_NONE) {
+ checkEarlyTriggerSequenceComplete(mRepeatingRequestId, lastFrameNumber);
+ mRepeatingRequestId = REQUEST_ID_NONE;
}
}
}
@@ -1021,14 +950,8 @@
return;
}
- try {
- if (mRemoteDevice != null) {
- mRemoteDevice.disconnect();
- }
- } catch (CameraRuntimeException e) {
- Log.e(TAG, "Exception while closing: ", e.asChecked());
- } catch (RemoteException e) {
- // impossible
+ if (mRemoteDevice != null) {
+ mRemoteDevice.disconnect();
}
// Only want to fire the onClosed callback once;
@@ -1297,14 +1220,14 @@
* Create a request-last-frame-numbers holder with a list of requests, request ID, and
* the last frame number returned by camera service.
*/
- public RequestLastFrameNumbersHolder(List<CaptureRequest> requestList, int requestId,
- long lastFrameNumber) {
+ public RequestLastFrameNumbersHolder(List<CaptureRequest> requestList, SubmitInfo requestInfo) {
long lastRegularFrameNumber = CaptureCallback.NO_FRAMES_CAPTURED;
long lastReprocessFrameNumber = CaptureCallback.NO_FRAMES_CAPTURED;
- long frameNumber = lastFrameNumber;
+ long frameNumber = requestInfo.getLastFrameNumber();
- if (lastFrameNumber < requestList.size() - 1) {
- throw new IllegalArgumentException("lastFrameNumber: " + lastFrameNumber +
+ if (requestInfo.getLastFrameNumber() < requestList.size() - 1) {
+ throw new IllegalArgumentException(
+ "lastFrameNumber: " + requestInfo.getLastFrameNumber() +
" should be at least " + (requestList.size() - 1) + " for the number of " +
" requests in the list: " + requestList.size());
}
@@ -1330,7 +1253,7 @@
mLastRegularFrameNumber = lastRegularFrameNumber;
mLastReprocessFrameNumber = lastReprocessFrameNumber;
- mRequestId = requestId;
+ mRequestId = requestInfo.getRequestId();
}
/**
diff --git a/core/java/android/hardware/camera2/impl/CameraMetadataNative.aidl b/core/java/android/hardware/camera2/impl/CameraMetadataNative.aidl
deleted file mode 100644
index 4a89129..0000000
--- a/core/java/android/hardware/camera2/impl/CameraMetadataNative.aidl
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright (C) 2013 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 android.hardware.camera2.impl;
-
-/** @hide */
-parcelable CameraMetadataNative;
diff --git a/core/java/android/hardware/camera2/impl/CameraMetadataNative.java b/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
index 12a2910..79eac26 100644
--- a/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
+++ b/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
@@ -58,6 +58,7 @@
import android.location.LocationManager;
import android.os.Parcelable;
import android.os.Parcel;
+import android.os.ServiceSpecificException;
import android.util.Log;
import android.util.Size;
@@ -363,13 +364,24 @@
* Set the global client-side vendor tag descriptor to allow use of vendor
* tags in camera applications.
*
- * @return int A native status_t value corresponding to one of the
- * {@link CameraBinderDecorator} integer constants.
- * @see CameraBinderDecorator#throwOnError
- *
+ * @throws ServiceSpecificException
* @hide
*/
- public static native int nativeSetupGlobalVendorTagDescriptor();
+ public static void setupGlobalVendorTagDescriptor() throws ServiceSpecificException {
+ int err = nativeSetupGlobalVendorTagDescriptor();
+ if (err != 0) {
+ throw new ServiceSpecificException(err, "Failure to set up global vendor tags");
+ }
+ }
+
+ /**
+ * Set the global client-side vendor tag descriptor to allow use of vendor
+ * tags in camera applications.
+ *
+ * @return int An error code corresponding to one of the
+ * {@link ICameraService} error constants, or 0 on success.
+ */
+ private static native int nativeSetupGlobalVendorTagDescriptor();
/**
* Set a camera metadata field to a value. The field definitions can be
diff --git a/core/java/android/hardware/camera2/impl/CaptureResultExtras.aidl b/core/java/android/hardware/camera2/impl/CaptureResultExtras.aidl
deleted file mode 100644
index ebc812a..0000000
--- a/core/java/android/hardware/camera2/impl/CaptureResultExtras.aidl
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright (C) 2014 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 android.hardware.camera2.impl;
-
-/** @hide */
-parcelable CaptureResultExtras;
diff --git a/core/java/android/hardware/camera2/impl/ICameraDeviceUserWrapper.java b/core/java/android/hardware/camera2/impl/ICameraDeviceUserWrapper.java
new file mode 100644
index 0000000..ddc3fd1
--- /dev/null
+++ b/core/java/android/hardware/camera2/impl/ICameraDeviceUserWrapper.java
@@ -0,0 +1,212 @@
+/*
+ * 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.
+ */
+
+package android.hardware.camera2.impl;
+
+import static android.hardware.camera2.CameraAccessException.CAMERA_DISABLED;
+import static android.hardware.camera2.CameraAccessException.CAMERA_DISCONNECTED;
+import static android.hardware.camera2.CameraAccessException.CAMERA_IN_USE;
+import static android.hardware.camera2.CameraAccessException.CAMERA_ERROR;
+import static android.hardware.camera2.CameraAccessException.MAX_CAMERAS_IN_USE;
+import static android.hardware.camera2.CameraAccessException.CAMERA_DEPRECATED_HAL;
+
+import android.hardware.ICameraService;
+import android.hardware.camera2.CameraManager;
+import android.hardware.camera2.CameraAccessException;
+import android.hardware.camera2.CaptureRequest;
+import android.hardware.camera2.ICameraDeviceUser;
+import android.hardware.camera2.impl.CameraMetadataNative;
+import android.hardware.camera2.params.OutputConfiguration;
+import android.hardware.camera2.utils.SubmitInfo;
+import android.os.RemoteException;
+import android.view.Surface;
+
+/**
+ * A wrapper around ICameraDeviceUser.
+ *
+ * Mainly used to convert ServiceSpecificExceptions to the correct
+ * checked / unchecked exception.
+ *
+ * @hide
+ */
+public class ICameraDeviceUserWrapper {
+
+ private final ICameraDeviceUser mRemoteDevice;
+
+ public ICameraDeviceUserWrapper(ICameraDeviceUser remoteDevice) {
+ if (remoteDevice == null) {
+ throw new NullPointerException("Remote device may not be null");
+ }
+ mRemoteDevice = remoteDevice;
+ }
+
+ public void disconnect() {
+ try {
+ mRemoteDevice.disconnect();
+ } catch (RemoteException t) {
+ // ignore binder errors for disconnect
+ }
+ }
+
+ public SubmitInfo submitRequest(CaptureRequest request, boolean streaming)
+ throws CameraAccessException {
+ try {
+ return mRemoteDevice.submitRequest(request, streaming);
+ } catch (Throwable t) {
+ CameraManager.throwAsPublicException(t);
+ throw new UnsupportedOperationException("Unexpected exception", t);
+ }
+ }
+
+ public SubmitInfo submitRequestList(CaptureRequest[] requestList, boolean streaming)
+ throws CameraAccessException {
+ try {
+ return mRemoteDevice.submitRequestList(requestList, streaming);
+ } catch (Throwable t) {
+ CameraManager.throwAsPublicException(t);
+ throw new UnsupportedOperationException("Unexpected exception", t);
+ }
+ }
+
+ public long cancelRequest(int requestId) throws CameraAccessException {
+ try {
+ return mRemoteDevice.cancelRequest(requestId);
+ } catch (Throwable t) {
+ CameraManager.throwAsPublicException(t);
+ throw new UnsupportedOperationException("Unexpected exception", t);
+ }
+ }
+
+ public void beginConfigure() throws CameraAccessException {
+ try {
+ mRemoteDevice.beginConfigure();
+ } catch (Throwable t) {
+ CameraManager.throwAsPublicException(t);
+ throw new UnsupportedOperationException("Unexpected exception", t);
+ }
+ }
+
+ public void endConfigure(boolean isConstrainedHighSpeed) throws CameraAccessException {
+ try {
+ mRemoteDevice.endConfigure(isConstrainedHighSpeed);
+ } catch (Throwable t) {
+ CameraManager.throwAsPublicException(t);
+ throw new UnsupportedOperationException("Unexpected exception", t);
+ }
+ }
+
+ public void deleteStream(int streamId) throws CameraAccessException {
+ try {
+ mRemoteDevice.deleteStream(streamId);
+ } catch (Throwable t) {
+ CameraManager.throwAsPublicException(t);
+ throw new UnsupportedOperationException("Unexpected exception", t);
+ }
+ }
+
+ public int createStream(OutputConfiguration outputConfiguration)
+ throws CameraAccessException {
+ try {
+ return mRemoteDevice.createStream(outputConfiguration);
+ } catch (Throwable t) {
+ CameraManager.throwAsPublicException(t);
+ throw new UnsupportedOperationException("Unexpected exception", t);
+ }
+ }
+
+ public int createInputStream(int width, int height, int format) throws CameraAccessException {
+ try {
+ return mRemoteDevice.createInputStream(width, height, format);
+ } catch (Throwable t) {
+ CameraManager.throwAsPublicException(t);
+ throw new UnsupportedOperationException("Unexpected exception", t);
+ }
+ }
+
+ public Surface getInputSurface() throws CameraAccessException {
+ try {
+ return mRemoteDevice.getInputSurface();
+ } catch (Throwable t) {
+ CameraManager.throwAsPublicException(t);
+ throw new UnsupportedOperationException("Unexpected exception", t);
+ }
+ }
+
+ public CameraMetadataNative createDefaultRequest(int templateId) throws CameraAccessException {
+ try {
+ return mRemoteDevice.createDefaultRequest(templateId);
+ } catch (Throwable t) {
+ CameraManager.throwAsPublicException(t);
+ throw new UnsupportedOperationException("Unexpected exception", t);
+ }
+ }
+
+ public CameraMetadataNative getCameraInfo() throws CameraAccessException {
+ try {
+ return mRemoteDevice.getCameraInfo();
+ } catch (Throwable t) {
+ CameraManager.throwAsPublicException(t);
+ throw new UnsupportedOperationException("Unexpected exception", t);
+ }
+ }
+
+ public void waitUntilIdle() throws CameraAccessException {
+ try {
+ mRemoteDevice.waitUntilIdle();
+ } catch (Throwable t) {
+ CameraManager.throwAsPublicException(t);
+ throw new UnsupportedOperationException("Unexpected exception", t);
+ }
+ }
+
+ public long flush() throws CameraAccessException {
+ try {
+ return mRemoteDevice.flush();
+ } catch (Throwable t) {
+ CameraManager.throwAsPublicException(t);
+ throw new UnsupportedOperationException("Unexpected exception", t);
+ }
+ }
+
+ public void prepare(int streamId) throws CameraAccessException {
+ try {
+ mRemoteDevice.prepare(streamId);
+ } catch (Throwable t) {
+ CameraManager.throwAsPublicException(t);
+ throw new UnsupportedOperationException("Unexpected exception", t);
+ }
+ }
+
+ public void tearDown(int streamId) throws CameraAccessException {
+ try {
+ mRemoteDevice.tearDown(streamId);
+ } catch (Throwable t) {
+ CameraManager.throwAsPublicException(t);
+ throw new UnsupportedOperationException("Unexpected exception", t);
+ }
+ }
+
+ public void prepare2(int maxCount, int streamId) throws CameraAccessException {
+ try {
+ mRemoteDevice.prepare2(maxCount, streamId);
+ } catch (Throwable t) {
+ CameraManager.throwAsPublicException(t);
+ throw new UnsupportedOperationException("Unexpected exception", t);
+ }
+ }
+
+
+}
diff --git a/core/java/android/hardware/camera2/legacy/BurstHolder.java b/core/java/android/hardware/camera2/legacy/BurstHolder.java
index e7b3682..23efe15 100644
--- a/core/java/android/hardware/camera2/legacy/BurstHolder.java
+++ b/core/java/android/hardware/camera2/legacy/BurstHolder.java
@@ -35,10 +35,10 @@
*
* @param requestId id of the burst request.
* @param repeating true if this burst is repeating.
- * @param requests a {@link List} of {@link CaptureRequest}s in this burst.
+ * @param requests the array of {@link CaptureRequest}s for this burst.
* @param jpegSurfaceIds a {@link Collection} of IDs for the surfaces that have jpeg outputs.
*/
- public BurstHolder(int requestId, boolean repeating, List<CaptureRequest> requests,
+ public BurstHolder(int requestId, boolean repeating, CaptureRequest[] requests,
Collection<Long> jpegSurfaceIds) {
mRequestBuilders = new ArrayList<>();
int i = 0;
diff --git a/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java b/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java
index 798c941..d01c275 100644
--- a/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java
+++ b/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java
@@ -16,6 +16,7 @@
package android.hardware.camera2.legacy;
+import android.hardware.ICameraService;
import android.hardware.Camera;
import android.hardware.Camera.CameraInfo;
import android.hardware.camera2.CameraAccessException;
@@ -23,12 +24,10 @@
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.ICameraDeviceCallbacks;
import android.hardware.camera2.ICameraDeviceUser;
-import android.hardware.camera2.utils.LongParcelable;
import android.hardware.camera2.impl.CameraMetadataNative;
import android.hardware.camera2.impl.CaptureResultExtras;
import android.hardware.camera2.params.OutputConfiguration;
-import android.hardware.camera2.utils.CameraBinderDecorator;
-import android.hardware.camera2.utils.CameraRuntimeException;
+import android.hardware.camera2.utils.SubmitInfo;
import android.os.ConditionVariable;
import android.os.IBinder;
import android.os.Looper;
@@ -36,6 +35,7 @@
import android.os.HandlerThread;
import android.os.Message;
import android.os.RemoteException;
+import android.os.ServiceSpecificException;
import android.util.Log;
import android.util.SparseArray;
import android.view.Surface;
@@ -93,7 +93,7 @@
private static int translateErrorsFromCamera1(int errorCode) {
if (errorCode == -EACCES) {
- return CameraBinderDecorator.PERMISSION_DENIED;
+ return ICameraService.ERROR_PERMISSION_DENIED;
}
return errorCode;
@@ -173,7 +173,7 @@
*
* @return int error code
*
- * @throws CameraRuntimeException if the camera open times out with ({@code CAMERA_ERROR})
+ * @throws ServiceSpecificException if the camera open times out with ({@code CAMERA_ERROR})
*/
public int waitForOpen(int timeoutMs) {
// Block until the camera is open asynchronously
@@ -186,7 +186,7 @@
Log.e(TAG, "connectBinderShim - Failed to release camera after timeout ", e);
}
- throw new CameraRuntimeException(CameraAccessException.CAMERA_ERROR);
+ throw new ServiceSpecificException(ICameraService.ERROR_INVALID_OPERATION);
}
return mInitErrors;
@@ -344,7 +344,7 @@
Camera legacyCamera = init.getCamera();
// Check errors old HAL initialization
- CameraBinderDecorator.throwOnError(initErrors);
+ LegacyExceptionUtils.throwOnServiceError(initErrors);
// Disable shutter sounds (this will work unconditionally) for api2 clients
legacyCamera.disableShutterSound();
@@ -356,8 +356,8 @@
try {
legacyParameters = legacyCamera.getParameters();
} catch (RuntimeException e) {
- throw new CameraRuntimeException(CameraAccessException.CAMERA_ERROR,
- "Unable to get initial parameters", e);
+ throw new ServiceSpecificException(ICameraService.ERROR_INVALID_OPERATION,
+ "Unable to get initial parameters: " + e.getMessage());
}
CameraCharacteristics characteristics =
@@ -386,101 +386,106 @@
}
@Override
- public int submitRequest(CaptureRequest request, boolean streaming,
- /*out*/LongParcelable lastFrameNumber) {
+ public SubmitInfo submitRequest(CaptureRequest request, boolean streaming) {
if (DEBUG) {
Log.d(TAG, "submitRequest called.");
}
if (mLegacyDevice.isClosed()) {
- Log.e(TAG, "Cannot submit request, device has been closed.");
- return -ENODEV;
+ String err = "Cannot submit request, device has been closed.";
+ Log.e(TAG, err);
+ throw new ServiceSpecificException(ICameraService.ERROR_DISCONNECTED, err);
}
synchronized(mConfigureLock) {
if (mConfiguring) {
- Log.e(TAG, "Cannot submit request, configuration change in progress.");
- return CameraBinderDecorator.INVALID_OPERATION;
+ String err = "Cannot submit request, configuration change in progress.";
+ Log.e(TAG, err);
+ throw new ServiceSpecificException(ICameraService.ERROR_INVALID_OPERATION, err);
}
}
- return mLegacyDevice.submitRequest(request, streaming, lastFrameNumber);
+ return mLegacyDevice.submitRequest(request, streaming);
}
@Override
- public int submitRequestList(List<CaptureRequest> request, boolean streaming,
- /*out*/LongParcelable lastFrameNumber) {
+ public SubmitInfo submitRequestList(CaptureRequest[] request, boolean streaming) {
if (DEBUG) {
Log.d(TAG, "submitRequestList called.");
}
if (mLegacyDevice.isClosed()) {
- Log.e(TAG, "Cannot submit request list, device has been closed.");
- return -ENODEV;
+ String err = "Cannot submit request list, device has been closed.";
+ Log.e(TAG, err);
+ throw new ServiceSpecificException(ICameraService.ERROR_DISCONNECTED, err);
}
synchronized(mConfigureLock) {
if (mConfiguring) {
- Log.e(TAG, "Cannot submit request, configuration change in progress.");
- return CameraBinderDecorator.INVALID_OPERATION;
+ String err = "Cannot submit request, configuration change in progress.";
+ Log.e(TAG, err);
+ throw new ServiceSpecificException(ICameraService.ERROR_INVALID_OPERATION, err);
}
}
- return mLegacyDevice.submitRequestList(request, streaming, lastFrameNumber);
+ return mLegacyDevice.submitRequestList(request, streaming);
}
@Override
- public int cancelRequest(int requestId, /*out*/LongParcelable lastFrameNumber) {
+ public long cancelRequest(int requestId) {
if (DEBUG) {
Log.d(TAG, "cancelRequest called.");
}
if (mLegacyDevice.isClosed()) {
- Log.e(TAG, "Cannot cancel request, device has been closed.");
- return -ENODEV;
+ String err = "Cannot cancel request, device has been closed.";
+ Log.e(TAG, err);
+ throw new ServiceSpecificException(ICameraService.ERROR_DISCONNECTED, err);
}
synchronized(mConfigureLock) {
if (mConfiguring) {
- Log.e(TAG, "Cannot cancel request, configuration change in progress.");
- return CameraBinderDecorator.INVALID_OPERATION;
+ String err = "Cannot cancel request, configuration change in progress.";
+ Log.e(TAG, err);
+ throw new ServiceSpecificException(ICameraService.ERROR_INVALID_OPERATION, err);
}
}
- long lastFrame = mLegacyDevice.cancelRequest(requestId);
- lastFrameNumber.setNumber(lastFrame);
- return CameraBinderDecorator.NO_ERROR;
+ return mLegacyDevice.cancelRequest(requestId);
}
@Override
- public int beginConfigure() {
+ public void beginConfigure() {
if (DEBUG) {
Log.d(TAG, "beginConfigure called.");
}
if (mLegacyDevice.isClosed()) {
- Log.e(TAG, "Cannot begin configure, device has been closed.");
- return -ENODEV;
+ String err = "Cannot begin configure, device has been closed.";
+ Log.e(TAG, err);
+ throw new ServiceSpecificException(ICameraService.ERROR_DISCONNECTED, err);
}
synchronized(mConfigureLock) {
if (mConfiguring) {
- Log.e(TAG, "Cannot begin configure, configuration change already in progress.");
- return CameraBinderDecorator.INVALID_OPERATION;
+ String err = "Cannot begin configure, configuration change already in progress.";
+ Log.e(TAG, err);
+ throw new ServiceSpecificException(ICameraService.ERROR_INVALID_OPERATION, err);
}
mConfiguring = true;
}
- return CameraBinderDecorator.NO_ERROR;
}
@Override
- public int endConfigure(boolean isConstrainedHighSpeed) {
+ public void endConfigure(boolean isConstrainedHighSpeed) {
if (DEBUG) {
Log.d(TAG, "endConfigure called.");
}
if (mLegacyDevice.isClosed()) {
- Log.e(TAG, "Cannot end configure, device has been closed.");
- return -ENODEV;
+ String err = "Cannot end configure, device has been closed.";
+ Log.e(TAG, err);
+ throw new ServiceSpecificException(ICameraService.ERROR_DISCONNECTED, err);
}
ArrayList<Surface> surfaces = null;
synchronized(mConfigureLock) {
if (!mConfiguring) {
- Log.e(TAG, "Cannot end configure, no configuration change in progress.");
- return CameraBinderDecorator.INVALID_OPERATION;
+ String err = "Cannot end configure, no configuration change in progress.";
+ Log.e(TAG, err);
+ throw new ServiceSpecificException(ICameraService.ERROR_INVALID_OPERATION, err);
}
int numSurfaces = mSurfaces.size();
if (numSurfaces > 0) {
@@ -491,32 +496,34 @@
}
mConfiguring = false;
}
- return mLegacyDevice.configureOutputs(surfaces);
+ mLegacyDevice.configureOutputs(surfaces);
}
@Override
- public int deleteStream(int streamId) {
+ public void deleteStream(int streamId) {
if (DEBUG) {
Log.d(TAG, "deleteStream called.");
}
if (mLegacyDevice.isClosed()) {
- Log.e(TAG, "Cannot delete stream, device has been closed.");
- return -ENODEV;
+ String err = "Cannot delete stream, device has been closed.";
+ Log.e(TAG, err);
+ throw new ServiceSpecificException(ICameraService.ERROR_DISCONNECTED, err);
}
synchronized(mConfigureLock) {
if (!mConfiguring) {
- Log.e(TAG, "Cannot delete stream, beginConfigure hasn't been called yet.");
- return CameraBinderDecorator.INVALID_OPERATION;
+ String err = "Cannot delete stream, no configuration change in progress.";
+ Log.e(TAG, err);
+ throw new ServiceSpecificException(ICameraService.ERROR_INVALID_OPERATION, err);
}
int index = mSurfaces.indexOfKey(streamId);
if (index < 0) {
- Log.e(TAG, "Cannot delete stream, stream id " + streamId + " doesn't exist.");
- return CameraBinderDecorator.BAD_VALUE;
+ String err = "Cannot delete stream, stream id " + streamId + " doesn't exist.";
+ Log.e(TAG, err);
+ throw new ServiceSpecificException(ICameraService.ERROR_ILLEGAL_ARGUMENT, err);
}
mSurfaces.removeAt(index);
}
- return CameraBinderDecorator.NO_ERROR;
}
@Override
@@ -525,18 +532,21 @@
Log.d(TAG, "createStream called.");
}
if (mLegacyDevice.isClosed()) {
- Log.e(TAG, "Cannot create stream, device has been closed.");
- return -ENODEV;
+ String err = "Cannot create stream, device has been closed.";
+ Log.e(TAG, err);
+ throw new ServiceSpecificException(ICameraService.ERROR_DISCONNECTED, err);
}
synchronized(mConfigureLock) {
if (!mConfiguring) {
- Log.e(TAG, "Cannot create stream, beginConfigure hasn't been called yet.");
- return CameraBinderDecorator.INVALID_OPERATION;
+ String err = "Cannot create stream, beginConfigure hasn't been called yet.";
+ Log.e(TAG, err);
+ throw new ServiceSpecificException(ICameraService.ERROR_INVALID_OPERATION, err);
}
if (outputConfiguration.getRotation() != OutputConfiguration.ROTATION_0) {
- Log.e(TAG, "Cannot create stream, stream rotation is not supported.");
- return CameraBinderDecorator.INVALID_OPERATION;
+ String err = "Cannot create stream, stream rotation is not supported.";
+ Log.e(TAG, err);
+ throw new ServiceSpecificException(ICameraService.ERROR_ILLEGAL_ARGUMENT, err);
}
int id = ++mSurfaceIdCounter;
mSurfaces.put(id, outputConfiguration.getSurface());
@@ -546,24 +556,27 @@
@Override
public int createInputStream(int width, int height, int format) {
- Log.e(TAG, "creating input stream is not supported on legacy devices");
- return CameraBinderDecorator.INVALID_OPERATION;
+ String err = "Creating input stream is not supported on legacy devices";
+ Log.e(TAG, err);
+ throw new ServiceSpecificException(ICameraService.ERROR_INVALID_OPERATION, err);
}
@Override
- public int getInputSurface(/*out*/ Surface surface) {
- Log.e(TAG, "getting input surface is not supported on legacy devices");
- return CameraBinderDecorator.INVALID_OPERATION;
+ public Surface getInputSurface() {
+ String err = "Getting input surface is not supported on legacy devices";
+ Log.e(TAG, err);
+ throw new ServiceSpecificException(ICameraService.ERROR_INVALID_OPERATION, err);
}
@Override
- public int createDefaultRequest(int templateId, /*out*/CameraMetadataNative request) {
+ public CameraMetadataNative createDefaultRequest(int templateId) {
if (DEBUG) {
Log.d(TAG, "createDefaultRequest called.");
}
if (mLegacyDevice.isClosed()) {
- Log.e(TAG, "Cannot create default request, device has been closed.");
- return -ENODEV;
+ String err = "Cannot create default request, device has been closed.";
+ Log.e(TAG, err);
+ throw new ServiceSpecificException(ICameraService.ERROR_DISCONNECTED, err);
}
CameraMetadataNative template;
@@ -571,99 +584,96 @@
template =
LegacyMetadataMapper.createRequestTemplate(mCameraCharacteristics, templateId);
} catch (IllegalArgumentException e) {
- Log.e(TAG, "createDefaultRequest - invalid templateId specified");
- return CameraBinderDecorator.BAD_VALUE;
+ String err = "createDefaultRequest - invalid templateId specified";
+ Log.e(TAG, err);
+ throw new ServiceSpecificException(ICameraService.ERROR_ILLEGAL_ARGUMENT, err);
}
- request.swap(template);
- return CameraBinderDecorator.NO_ERROR;
+ return template;
}
@Override
- public int getCameraInfo(/*out*/CameraMetadataNative info) {
+ public CameraMetadataNative getCameraInfo() {
if (DEBUG) {
Log.d(TAG, "getCameraInfo called.");
}
// TODO: implement getCameraInfo.
Log.e(TAG, "getCameraInfo unimplemented.");
- return CameraBinderDecorator.NO_ERROR;
+ return null;
}
@Override
- public int waitUntilIdle() throws RemoteException {
+ public void waitUntilIdle() throws RemoteException {
if (DEBUG) {
Log.d(TAG, "waitUntilIdle called.");
}
if (mLegacyDevice.isClosed()) {
- Log.e(TAG, "Cannot wait until idle, device has been closed.");
- return -ENODEV;
+ String err = "Cannot wait until idle, device has been closed.";
+ Log.e(TAG, err);
+ throw new ServiceSpecificException(ICameraService.ERROR_DISCONNECTED, err);
}
synchronized(mConfigureLock) {
if (mConfiguring) {
- Log.e(TAG, "Cannot wait until idle, configuration change in progress.");
- return CameraBinderDecorator.INVALID_OPERATION;
+ String err = "Cannot wait until idle, configuration change in progress.";
+ Log.e(TAG, err);
+ throw new ServiceSpecificException(ICameraService.ERROR_INVALID_OPERATION, err);
}
}
mLegacyDevice.waitUntilIdle();
- return CameraBinderDecorator.NO_ERROR;
}
@Override
- public int flush(/*out*/LongParcelable lastFrameNumber) {
+ public long flush() {
if (DEBUG) {
Log.d(TAG, "flush called.");
}
if (mLegacyDevice.isClosed()) {
- Log.e(TAG, "Cannot flush, device has been closed.");
- return -ENODEV;
+ String err = "Cannot flush, device has been closed.";
+ Log.e(TAG, err);
+ throw new ServiceSpecificException(ICameraService.ERROR_DISCONNECTED, err);
}
synchronized(mConfigureLock) {
if (mConfiguring) {
- Log.e(TAG, "Cannot flush, configuration change in progress.");
- return CameraBinderDecorator.INVALID_OPERATION;
+ String err = "Cannot flush, configuration change in progress.";
+ Log.e(TAG, err);
+ throw new ServiceSpecificException(ICameraService.ERROR_INVALID_OPERATION, err);
}
}
- long lastFrame = mLegacyDevice.flush();
- if (lastFrameNumber != null) {
- lastFrameNumber.setNumber(lastFrame);
- }
- return CameraBinderDecorator.NO_ERROR;
+ return mLegacyDevice.flush();
}
- public int prepare(int streamId) {
+ public void prepare(int streamId) {
if (DEBUG) {
Log.d(TAG, "prepare called.");
}
if (mLegacyDevice.isClosed()) {
- Log.e(TAG, "Cannot prepare stream, device has been closed.");
- return -ENODEV;
+ String err = "Cannot prepare stream, device has been closed.";
+ Log.e(TAG, err);
+ throw new ServiceSpecificException(ICameraService.ERROR_DISCONNECTED, err);
}
// LEGACY doesn't support actual prepare, just signal success right away
mCameraCallbacks.onPrepared(streamId);
-
- return CameraBinderDecorator.NO_ERROR;
}
- public int prepare2(int maxCount, int streamId) {
+ public void prepare2(int maxCount, int streamId) {
// We don't support this in LEGACY mode.
- return prepare(streamId);
+ prepare(streamId);
}
- public int tearDown(int streamId) {
+ public void tearDown(int streamId) {
if (DEBUG) {
Log.d(TAG, "tearDown called.");
}
if (mLegacyDevice.isClosed()) {
- Log.e(TAG, "Cannot tear down stream, device has been closed.");
- return -ENODEV;
+ String err = "Cannot tear down stream, device has been closed.";
+ Log.e(TAG, err);
+ throw new ServiceSpecificException(ICameraService.ERROR_DISCONNECTED, err);
}
// LEGACY doesn't support actual teardown, so just a no-op
-
- return CameraBinderDecorator.NO_ERROR;
}
@Override
diff --git a/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java b/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java
index fddfbde..e62df3c 100644
--- a/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java
+++ b/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java
@@ -26,14 +26,13 @@
import android.hardware.camera2.ICameraDeviceCallbacks;
import android.hardware.camera2.params.StreamConfigurationMap;
import android.hardware.camera2.utils.ArrayUtils;
-import android.hardware.camera2.utils.CameraBinderDecorator;
-import android.hardware.camera2.utils.LongParcelable;
+import android.hardware.camera2.utils.SubmitInfo;
import android.hardware.camera2.impl.CameraMetadataNative;
-import android.hardware.camera2.utils.CameraRuntimeException;
import android.os.ConditionVariable;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.RemoteException;
+import android.os.ServiceSpecificException;
import android.util.Log;
import android.util.Pair;
import android.util.Size;
@@ -45,7 +44,6 @@
import java.util.List;
import static android.hardware.camera2.legacy.LegacyExceptionUtils.*;
-import static android.hardware.camera2.utils.CameraBinderDecorator.*;
import static com.android.internal.util.Preconditions.*;
/**
@@ -357,9 +355,9 @@
if (success) {
mConfiguredSurfaces = outputs != null ? new ArrayList<>(outputs) : null;
} else {
- return CameraBinderDecorator.INVALID_OPERATION;
+ return LegacyExceptionUtils.INVALID_OPERATION;
}
- return CameraBinderDecorator.NO_ERROR;
+ return LegacyExceptionUtils.NO_ERROR;
}
/**
@@ -367,17 +365,16 @@
*
* @param requestList a list of capture requests to execute.
* @param repeating {@code true} if this burst is repeating.
- * @param frameNumber an output argument that contains either the frame number of the last frame
- * that will be returned for this request, or the frame number of the last
- * frame that will be returned for the current repeating request if this
- * burst is set to be repeating.
- * @return the request id.
+ * @return the submission info, including the new request id, and the last frame number, which
+ * contains either the frame number of the last frame that will be returned for this request,
+ * or the frame number of the last frame that will be returned for the current repeating
+ * request if this burst is set to be repeating.
*/
- public int submitRequestList(List<CaptureRequest> requestList, boolean repeating,
- /*out*/LongParcelable frameNumber) {
- if (requestList == null || requestList.isEmpty()) {
+ public SubmitInfo submitRequestList(CaptureRequest[] requestList, boolean repeating) {
+ if (requestList == null || requestList.length == 0) {
Log.e(TAG, "submitRequestList - Empty/null requests are not allowed");
- return BAD_VALUE;
+ throw new ServiceSpecificException(BAD_VALUE,
+ "submitRequestList - Empty/null requests are not allowed");
}
List<Long> surfaceIds = (mConfiguredSurfaces == null) ? new ArrayList<Long>() :
@@ -388,28 +385,33 @@
if (request.getTargets().isEmpty()) {
Log.e(TAG, "submitRequestList - "
+ "Each request must have at least one Surface target");
- return BAD_VALUE;
+ throw new ServiceSpecificException(BAD_VALUE,
+ "submitRequestList - "
+ + "Each request must have at least one Surface target");
}
for (Surface surface : request.getTargets()) {
if (surface == null) {
Log.e(TAG, "submitRequestList - Null Surface targets are not allowed");
- return BAD_VALUE;
+ throw new ServiceSpecificException(BAD_VALUE,
+ "submitRequestList - Null Surface targets are not allowed");
} else if (mConfiguredSurfaces == null) {
Log.e(TAG, "submitRequestList - must configure " +
" device with valid surfaces before submitting requests");
- return INVALID_OPERATION;
+ throw new ServiceSpecificException(INVALID_OPERATION,
+ "submitRequestList - must configure " +
+ " device with valid surfaces before submitting requests");
} else if (!containsSurfaceId(surface, surfaceIds)) {
Log.e(TAG, "submitRequestList - cannot use a surface that wasn't configured");
- return BAD_VALUE;
+ throw new ServiceSpecificException(BAD_VALUE,
+ "submitRequestList - cannot use a surface that wasn't configured");
}
}
}
// TODO: further validation of request here
mIdle.close();
- return mRequestThreadManager.submitCaptureRequests(requestList, repeating,
- frameNumber);
+ return mRequestThreadManager.submitCaptureRequests(requestList, repeating);
}
/**
@@ -417,17 +419,14 @@
*
* @param request the capture request to execute.
* @param repeating {@code true} if this request is repeating.
- * @param frameNumber an output argument that contains either the frame number of the last frame
- * that will be returned for this request, or the frame number of the last
- * frame that will be returned for the current repeating request if this
- * request is set to be repeating.
- * @return the request id.
+ * @return the submission info, including the new request id, and the last frame number, which
+ * contains either the frame number of the last frame that will be returned for this request,
+ * or the frame number of the last frame that will be returned for the current repeating
+ * request if this burst is set to be repeating.
*/
- public int submitRequest(CaptureRequest request, boolean repeating,
- /*out*/LongParcelable frameNumber) {
- ArrayList<CaptureRequest> requestList = new ArrayList<CaptureRequest>();
- requestList.add(request);
- return submitRequestList(requestList, repeating, frameNumber);
+ public SubmitInfo submitRequest(CaptureRequest request, boolean repeating) {
+ CaptureRequest[] requestList = { request };
+ return submitRequestList(requestList, repeating);
}
/**
@@ -493,7 +492,7 @@
protected void finalize() throws Throwable {
try {
close();
- } catch (CameraRuntimeException e) {
+ } catch (ServiceSpecificException e) {
Log.e(TAG, "Got error while trying to finalize, ignoring: " + e.getMessage());
} finally {
super.finalize();
diff --git a/core/java/android/hardware/camera2/legacy/LegacyExceptionUtils.java b/core/java/android/hardware/camera2/legacy/LegacyExceptionUtils.java
index 4501e81..93d6001 100644
--- a/core/java/android/hardware/camera2/legacy/LegacyExceptionUtils.java
+++ b/core/java/android/hardware/camera2/legacy/LegacyExceptionUtils.java
@@ -16,10 +16,11 @@
package android.hardware.camera2.legacy;
-import android.hardware.camera2.utils.CameraBinderDecorator;
+import android.hardware.ICameraService;
+import android.os.ServiceSpecificException;
import android.util.AndroidException;
-import static android.system.OsConstants.ENODEV;
+import static android.system.OsConstants.*;
/**
* Utility class containing exception handling used solely by the compatibility mode shim.
@@ -27,6 +28,14 @@
public class LegacyExceptionUtils {
private static final String TAG = "LegacyExceptionUtils";
+ public static final int NO_ERROR = 0;
+ public static final int PERMISSION_DENIED = -EPERM;
+ public static final int ALREADY_EXISTS = -EEXIST;
+ public static final int BAD_VALUE = -EINVAL;
+ public static final int DEAD_OBJECT = -ENOSYS;
+ public static final int INVALID_OPERATION = -EPIPE;
+ public static final int TIMED_OUT = -ETIMEDOUT;
+
/**
* Checked exception thrown when a BufferQueue has been abandoned by its consumer.
*/
@@ -58,8 +67,8 @@
* @return {@code errorFlag} if the value was non-negative, throws otherwise.
*/
public static int throwOnError(int errorFlag) throws BufferQueueAbandonedException {
- if (errorFlag == CameraBinderDecorator.NO_ERROR) {
- return CameraBinderDecorator.NO_ERROR;
+ if (errorFlag == NO_ERROR) {
+ return NO_ERROR;
} else if (errorFlag == -ENODEV) {
throw new BufferQueueAbandonedException();
}
@@ -70,6 +79,59 @@
return errorFlag;
}
+ /**
+ * Throw error codes returned by the camera service as exceptions.
+ *
+ * @param errorFlag error to throw as an exception.
+ */
+ public static void throwOnServiceError(int errorFlag) {
+ int errorCode = ICameraService.ERROR_INVALID_OPERATION;
+ String errorMsg;
+
+ if (errorFlag >= NO_ERROR) {
+ return;
+ } else if (errorFlag == PERMISSION_DENIED) {
+ errorCode = ICameraService.ERROR_PERMISSION_DENIED;
+ errorMsg = "Lacking privileges to access camera service";
+ } else if (errorFlag == ALREADY_EXISTS) {
+ // This should be handled at the call site. Typically this isn't bad,
+ // just means we tried to do an operation that already completed.
+ return;
+ } else if (errorFlag == BAD_VALUE) {
+ errorCode = ICameraService.ERROR_ILLEGAL_ARGUMENT;
+ errorMsg = "Bad argument passed to camera service";
+ } else if (errorFlag == DEAD_OBJECT) {
+ errorCode = ICameraService.ERROR_DISCONNECTED;
+ errorMsg = "Camera service not available";
+ } else if (errorFlag == TIMED_OUT) {
+ errorCode = ICameraService.ERROR_INVALID_OPERATION;
+ errorMsg = "Operation timed out in camera service";
+ } else if (errorFlag == -EACCES) {
+ errorCode = ICameraService.ERROR_DISABLED;
+ errorMsg = "Camera disabled by policy";
+ } else if (errorFlag == -EBUSY) {
+ errorCode = ICameraService.ERROR_CAMERA_IN_USE;
+ errorMsg = "Camera already in use";
+ } else if (errorFlag == -EUSERS) {
+ errorCode = ICameraService.ERROR_MAX_CAMERAS_IN_USE;
+ errorMsg = "Maximum number of cameras in use";
+ } else if (errorFlag == -ENODEV) {
+ errorCode = ICameraService.ERROR_DISCONNECTED;
+ errorMsg = "Camera device not available";
+ } else if (errorFlag == -EOPNOTSUPP) {
+ errorCode = ICameraService.ERROR_DEPRECATED_HAL;
+ errorMsg = "Deprecated camera HAL does not support this";
+ } else if (errorFlag == INVALID_OPERATION) {
+ errorCode = ICameraService.ERROR_INVALID_OPERATION;
+ errorMsg = "Illegal state encountered in camera service.";
+ } else {
+ errorCode = ICameraService.ERROR_INVALID_OPERATION;
+ errorMsg = "Unknown camera device error " + errorFlag;
+ }
+
+ throw new ServiceSpecificException(errorCode, errorMsg);
+ }
+
private LegacyExceptionUtils() {
throw new AssertionError();
}
diff --git a/core/java/android/hardware/camera2/legacy/RequestQueue.java b/core/java/android/hardware/camera2/legacy/RequestQueue.java
index c995029..8f252a1 100644
--- a/core/java/android/hardware/camera2/legacy/RequestQueue.java
+++ b/core/java/android/hardware/camera2/legacy/RequestQueue.java
@@ -16,7 +16,7 @@
package android.hardware.camera2.legacy;
import android.hardware.camera2.CaptureRequest;
-import android.hardware.camera2.utils.LongParcelable;
+import android.hardware.camera2.utils.SubmitInfo;
import android.util.Log;
import android.util.Pair;
@@ -111,31 +111,29 @@
*
* @param requests the burst of requests to add to the queue.
* @param repeating true if the burst is repeating.
- * @param frameNumber an output argument that contains either the frame number of the last frame
- * that will be returned for this request, or the frame number of the last
- * frame that will be returned for the current repeating request if this
- * burst is set to be repeating.
- * @return the request id.
+ * @return the submission info, including the new request id, and the last frame number, which
+ * contains either the frame number of the last frame that will be returned for this request,
+ * or the frame number of the last frame that will be returned for the current repeating
+ * request if this burst is set to be repeating.
*/
- public synchronized int submit(List<CaptureRequest> requests, boolean repeating,
- /*out*/LongParcelable frameNumber) {
+ public synchronized SubmitInfo submit(CaptureRequest[] requests, boolean repeating) {
int requestId = mCurrentRequestId++;
BurstHolder burst = new BurstHolder(requestId, repeating, requests, mJpegSurfaceIds);
- long ret = INVALID_FRAME;
+ long lastFrame = INVALID_FRAME;
if (burst.isRepeating()) {
Log.i(TAG, "Repeating capture request set.");
if (mRepeatingRequest != null) {
- ret = (mCurrentRepeatingFrameNumber == INVALID_FRAME) ? INVALID_FRAME :
+ lastFrame = (mCurrentRepeatingFrameNumber == INVALID_FRAME) ? INVALID_FRAME :
mCurrentRepeatingFrameNumber - 1;
}
mCurrentRepeatingFrameNumber = INVALID_FRAME;
mRepeatingRequest = burst;
} else {
mRequestQueue.offer(burst);
- ret = calculateLastFrame(burst.getRequestId());
+ lastFrame = calculateLastFrame(burst.getRequestId());
}
- frameNumber.setNumber(ret);
- return requestId;
+ SubmitInfo info = new SubmitInfo(requestId, lastFrame);
+ return info;
}
private long calculateLastFrame(int requestId) {
diff --git a/core/java/android/hardware/camera2/legacy/RequestThreadManager.java b/core/java/android/hardware/camera2/legacy/RequestThreadManager.java
index 4866598..1ca7ddf 100644
--- a/core/java/android/hardware/camera2/legacy/RequestThreadManager.java
+++ b/core/java/android/hardware/camera2/legacy/RequestThreadManager.java
@@ -21,7 +21,7 @@
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.impl.CameraDeviceImpl;
-import android.hardware.camera2.utils.LongParcelable;
+import android.hardware.camera2.utils.SubmitInfo;
import android.hardware.camera2.utils.SizeAreaComparator;
import android.hardware.camera2.impl.CameraMetadataNative;
import android.os.ConditionVariable;
@@ -1008,21 +1008,19 @@
*
* @param requests the burst of requests to add to the queue.
* @param repeating true if the burst is repeating.
- * @param frameNumber an output argument that contains either the frame number of the last frame
- * that will be returned for this request, or the frame number of the last
- * frame that will be returned for the current repeating request if this
- * burst is set to be repeating.
- * @return the request id.
+ * @return the submission info, including the new request id, and the last frame number, which
+ * contains either the frame number of the last frame that will be returned for this request,
+ * or the frame number of the last frame that will be returned for the current repeating
+ * request if this burst is set to be repeating.
*/
- public int submitCaptureRequests(List<CaptureRequest> requests, boolean repeating,
- /*out*/LongParcelable frameNumber) {
+ public SubmitInfo submitCaptureRequests(CaptureRequest[] requests, boolean repeating) {
Handler handler = mRequestThread.waitAndGetHandler();
- int ret;
+ SubmitInfo info;
synchronized (mIdleLock) {
- ret = mRequestQueue.submit(requests, repeating, frameNumber);
+ info = mRequestQueue.submit(requests, repeating);
handler.sendEmptyMessage(MSG_SUBMIT_CAPTURE_REQUEST);
}
- return ret;
+ return info;
}
/**
diff --git a/core/java/android/hardware/camera2/params/OutputConfiguration.aidl b/core/java/android/hardware/camera2/params/OutputConfiguration.aidl
deleted file mode 100644
index 0921cd8..0000000
--- a/core/java/android/hardware/camera2/params/OutputConfiguration.aidl
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright (C) 2015 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 android.hardware.camera2.params;
-
-/** @hide */
-parcelable OutputConfiguration;
diff --git a/core/java/android/hardware/camera2/params/OutputConfiguration.java b/core/java/android/hardware/camera2/params/OutputConfiguration.java
index 4407e55..cd0c474 100644
--- a/core/java/android/hardware/camera2/params/OutputConfiguration.java
+++ b/core/java/android/hardware/camera2/params/OutputConfiguration.java
@@ -21,11 +21,11 @@
import android.hardware.camera2.CameraDevice;
import android.hardware.camera2.utils.HashCodeHelpers;
import android.hardware.camera2.utils.SurfaceUtils;
+import android.os.Parcel;
+import android.os.Parcelable;
import android.util.Log;
import android.util.Size;
import android.view.Surface;
-import android.os.Parcel;
-import android.os.Parcelable;
import static com.android.internal.util.Preconditions.*;
diff --git a/core/java/android/hardware/camera2/params/VendorTagDescriptor.java b/core/java/android/hardware/camera2/params/VendorTagDescriptor.java
new file mode 100644
index 0000000..ea424e5
--- /dev/null
+++ b/core/java/android/hardware/camera2/params/VendorTagDescriptor.java
@@ -0,0 +1,67 @@
+/*
+ * 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.
+ */
+
+package android.hardware.camera2.params;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.Log;
+
+/**
+ * A class for describing the vendor tags declared by a camera HAL module.
+ * Generally only used by the native side of
+ * android.hardware.camera2.impl.CameraMetadataNative
+ *
+ * @hide
+ */
+public final class VendorTagDescriptor implements Parcelable {
+
+ private VendorTagDescriptor(Parcel source) {
+ }
+
+ public static final Parcelable.Creator<VendorTagDescriptor> CREATOR =
+ new Parcelable.Creator<VendorTagDescriptor>() {
+ @Override
+ public VendorTagDescriptor createFromParcel(Parcel source) {
+ try {
+ VendorTagDescriptor vendorDescriptor = new VendorTagDescriptor(source);
+ return vendorDescriptor;
+ } catch (Exception e) {
+ Log.e(TAG, "Exception creating VendorTagDescriptor from parcel", e);
+ return null;
+ }
+ }
+
+ @Override
+ public VendorTagDescriptor[] newArray(int size) {
+ return new VendorTagDescriptor[size];
+ }
+ };
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ if (dest == null) {
+ throw new IllegalArgumentException("dest must not be null");
+ }
+ }
+
+ private static final String TAG = "VendorTagDescriptor";
+}
diff --git a/core/java/android/hardware/camera2/utils/BinderHolder.aidl b/core/java/android/hardware/camera2/utils/BinderHolder.aidl
deleted file mode 100644
index f39d645..0000000
--- a/core/java/android/hardware/camera2/utils/BinderHolder.aidl
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright (C) 2013 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 android.hardware.camera2.utils;
-
-/** @hide */
-parcelable BinderHolder;
diff --git a/core/java/android/hardware/camera2/utils/BinderHolder.java b/core/java/android/hardware/camera2/utils/BinderHolder.java
deleted file mode 100644
index 9eea390..0000000
--- a/core/java/android/hardware/camera2/utils/BinderHolder.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (C) 2013 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 android.hardware.camera2.utils;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.os.IBinder;
-
-/**
- * @hide
- */
-public class BinderHolder implements Parcelable {
- private IBinder mBinder = null;
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeStrongBinder(mBinder);
- }
-
- public void readFromParcel(Parcel src) {
- mBinder = src.readStrongBinder();
- }
-
- public static final Parcelable.Creator<BinderHolder> CREATOR =
- new Parcelable.Creator<BinderHolder>() {
- @Override
- public BinderHolder createFromParcel(Parcel in) {
- return new BinderHolder(in);
- }
-
- @Override
- public BinderHolder[] newArray(int size) {
- return new BinderHolder[size];
- }
- };
-
- public IBinder getBinder() {
- return mBinder;
- }
-
- public void setBinder(IBinder binder) {
- mBinder = binder;
- }
-
- public BinderHolder() {}
-
- public BinderHolder(IBinder binder) {
- mBinder = binder;
- }
-
- private BinderHolder(Parcel in) {
- mBinder = in.readStrongBinder();
- }
-}
-
diff --git a/core/java/android/hardware/camera2/utils/CameraBinderDecorator.java b/core/java/android/hardware/camera2/utils/CameraBinderDecorator.java
deleted file mode 100644
index 162edc9..0000000
--- a/core/java/android/hardware/camera2/utils/CameraBinderDecorator.java
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- * Copyright (C) 2013 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 android.hardware.camera2.utils;
-
-import static android.hardware.camera2.CameraAccessException.CAMERA_DISABLED;
-import static android.hardware.camera2.CameraAccessException.CAMERA_DISCONNECTED;
-import static android.hardware.camera2.CameraAccessException.CAMERA_IN_USE;
-import static android.hardware.camera2.CameraAccessException.CAMERA_ERROR;
-import static android.hardware.camera2.CameraAccessException.MAX_CAMERAS_IN_USE;
-import static android.hardware.camera2.CameraAccessException.CAMERA_DEPRECATED_HAL;
-import static android.system.OsConstants.*;
-
-import android.os.DeadObjectException;
-import android.os.RemoteException;
-
-import java.lang.reflect.Method;
-
-/**
- * Translate camera device status_t return values into exceptions.
- *
- * @see android.hardware.camera2.utils.CameraBinderDecorator#newInstance
- * @hide
- */
-public class CameraBinderDecorator {
-
- public static final int NO_ERROR = 0;
- public static final int PERMISSION_DENIED = -EPERM;
- public static final int ALREADY_EXISTS = -EEXIST;
- public static final int BAD_VALUE = -EINVAL;
- public static final int DEAD_OBJECT = -ENOSYS;
- public static final int INVALID_OPERATION = -EPIPE;
- public static final int TIMED_OUT = -ETIMEDOUT;
-
- /**
- * TODO: add as error codes in Errors.h
- * - POLICY_PROHIBITS
- * - RESOURCE_BUSY
- * - NO_SUCH_DEVICE
- * - NOT_SUPPORTED
- * - TOO_MANY_USERS
- */
-
- static class CameraBinderDecoratorListener implements Decorator.DecoratorListener {
-
- @Override
- public void onBeforeInvocation(Method m, Object[] args) {
- }
-
- @Override
- public void onAfterInvocation(Method m, Object[] args, Object result) {
- // int return type => status_t => convert to exception
- if (m.getReturnType() == Integer.TYPE) {
- int returnValue = (Integer) result;
- throwOnError(returnValue);
- }
- }
-
- @Override
- public boolean onCatchException(Method m, Object[] args, Throwable t) {
-
- if (t instanceof DeadObjectException) {
- throw new CameraRuntimeException(CAMERA_DISCONNECTED,
- "Process hosting the camera service has died unexpectedly",
- t);
- } else if (t instanceof RemoteException) {
- throw new UnsupportedOperationException("An unknown RemoteException was thrown" +
- " which should never happen.", t);
- }
-
- return false;
- }
-
- @Override
- public void onFinally(Method m, Object[] args) {
- }
-
- }
-
- /**
- * Throw error codes returned by the camera service as exceptions.
- *
- * @param errorFlag error to throw as an exception.
- */
- public static void throwOnError(int errorFlag) {
- if (errorFlag == NO_ERROR) {
- return;
- } else if (errorFlag == PERMISSION_DENIED) {
- throw new SecurityException("Lacking privileges to access camera service");
- } else if (errorFlag == ALREADY_EXISTS) {
- // This should be handled at the call site. Typically this isn't bad,
- // just means we tried to do an operation that already completed.
- return;
- } else if (errorFlag == BAD_VALUE) {
- throw new IllegalArgumentException("Bad argument passed to camera service");
- } else if (errorFlag == DEAD_OBJECT) {
- throw new CameraRuntimeException(CAMERA_DISCONNECTED);
- } else if (errorFlag == TIMED_OUT) {
- throw new CameraRuntimeException(CAMERA_ERROR,
- "Operation timed out in camera service");
- } else if (errorFlag == -EACCES) {
- throw new CameraRuntimeException(CAMERA_DISABLED);
- } else if (errorFlag == -EBUSY) {
- throw new CameraRuntimeException(CAMERA_IN_USE);
- } else if (errorFlag == -EUSERS) {
- throw new CameraRuntimeException(MAX_CAMERAS_IN_USE);
- } else if (errorFlag == -ENODEV) {
- throw new CameraRuntimeException(CAMERA_DISCONNECTED);
- } else if (errorFlag == -EOPNOTSUPP) {
- throw new CameraRuntimeException(CAMERA_DEPRECATED_HAL);
- } else if (errorFlag == INVALID_OPERATION) {
- throw new CameraRuntimeException(CAMERA_ERROR,
- "Illegal state encountered in camera service.");
- }
-
- /**
- * Trap the rest of the negative return values. If we have known
- * error codes i.e. ALREADY_EXISTS that aren't really runtime
- * errors, then add them to the top switch statement
- */
- if (errorFlag < 0) {
- throw new CameraRuntimeException(CAMERA_ERROR,
- String.format("Unknown camera device error %d", errorFlag));
- }
- }
-
- /**
- * <p>
- * Wraps the type T with a proxy that will check 'status_t' return codes
- * from the native side of the camera service, and throw Java exceptions
- * automatically based on the code.
- * </p>
- * <p>
- * In addition it also rewrites binder's RemoteException into either a
- * CameraAccessException or an UnsupportedOperationException.
- * </p>
- * <p>
- * As a result of calling any method on the proxy, RemoteException is
- * guaranteed never to be thrown.
- * </p>
- *
- * @param obj object that will serve as the target for all method calls
- * @param <T> the type of the element you want to wrap. This must be an interface.
- * @return a proxy that will intercept all invocations to obj
- */
- public static <T> T newInstance(T obj) {
- return Decorator.<T> newInstance(obj, new CameraBinderDecoratorListener());
- }
-}
diff --git a/core/java/android/hardware/camera2/utils/CameraRuntimeException.java b/core/java/android/hardware/camera2/utils/CameraRuntimeException.java
deleted file mode 100644
index 9ed88a9..0000000
--- a/core/java/android/hardware/camera2/utils/CameraRuntimeException.java
+++ /dev/null
@@ -1,63 +0,0 @@
-package android.hardware.camera2.utils;
-
-import android.hardware.camera2.CameraAccessException;
-
-/**
- * @hide
- */
-public class CameraRuntimeException extends RuntimeException {
-
- private final int mReason;
- private String mMessage;
- private Throwable mCause;
-
- public final int getReason() {
- return mReason;
- }
-
- public CameraRuntimeException(int problem) {
- super();
- mReason = problem;
- }
-
- public CameraRuntimeException(int problem, String message) {
- super(message);
- mReason = problem;
- mMessage = message;
- }
-
- public CameraRuntimeException(int problem, String message, Throwable cause) {
- super(message, cause);
- mReason = problem;
- mMessage = message;
- mCause = cause;
- }
-
- public CameraRuntimeException(int problem, Throwable cause) {
- super(cause);
- mReason = problem;
- mCause = cause;
- }
-
- /**
- * Recreate this exception as the CameraAccessException equivalent.
- * @return CameraAccessException
- */
- public CameraAccessException asChecked() {
- CameraAccessException e;
-
- if (mMessage != null && mCause != null) {
- e = new CameraAccessException(mReason, mMessage, mCause);
- } else if (mMessage != null) {
- e = new CameraAccessException(mReason, mMessage);
- } else if (mCause != null) {
- e = new CameraAccessException(mReason, mCause);
- } else {
- e = new CameraAccessException(mReason);
- }
- // throw and catch, so java has a chance to fill out the stack trace
- e.setStackTrace(this.getStackTrace());
-
- return e;
- }
-}
diff --git a/core/java/android/hardware/camera2/utils/CameraServiceBinderDecorator.java b/core/java/android/hardware/camera2/utils/CameraServiceBinderDecorator.java
deleted file mode 100644
index c1fb6b1..0000000
--- a/core/java/android/hardware/camera2/utils/CameraServiceBinderDecorator.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (C) 2014 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 android.hardware.camera2.utils;
-
-import android.os.DeadObjectException;
-import android.os.RemoteException;
-import android.util.Log;
-
-import java.lang.reflect.Method;
-
-/**
- * Translate camera service status_t return values into exceptions.
- *
- * @see android.hardware.camera2.utils.CameraBinderDecorator#newInstance
- * @hide
- */
-public class CameraServiceBinderDecorator extends CameraBinderDecorator {
-
- private static final String TAG = "CameraServiceBinderDecorator";
-
- static class CameraServiceBinderDecoratorListener
- extends CameraBinderDecorator.CameraBinderDecoratorListener {
-
- // Pass through remote exceptions, unlike CameraBinderDecorator
- @Override
- public boolean onCatchException(Method m, Object[] args, Throwable t) {
-
- if (t instanceof DeadObjectException) {
- // Can sometimes happen (camera service died)
- // Pass on silently
- } else if (t instanceof RemoteException) {
- // Some other kind of remote exception - this is not normal, so let's at least
- // note it before moving on
- Log.e(TAG, "Unexpected RemoteException from camera service call.", t);
- }
- // All other exceptions also get sent onward
- return false;
- }
-
- }
-
- /**
- * <p>
- * Wraps the type T with a proxy that will check 'status_t' return codes
- * from the native side of the camera service, and throw Java exceptions
- * automatically based on the code.
- * </p>
- *
- * @param obj object that will serve as the target for all method calls
- * @param <T> the type of the element you want to wrap. This must be an interface.
- * @return a proxy that will intercept all invocations to obj
- */
- public static <T> T newInstance(T obj) {
- return Decorator.<T> newInstance(obj, new CameraServiceBinderDecoratorListener());
- }
-}
diff --git a/core/java/android/hardware/camera2/utils/Decorator.java b/core/java/android/hardware/camera2/utils/Decorator.java
deleted file mode 100644
index 5826497..0000000
--- a/core/java/android/hardware/camera2/utils/Decorator.java
+++ /dev/null
@@ -1,92 +0,0 @@
-
-package android.hardware.camera2.utils;
-
-import java.lang.reflect.*;
-
-/**
- * This is an implementation of the 'decorator' design pattern using Java's proxy mechanism.
- *
- * @see android.hardware.camera2.utils.Decorator#newInstance
- *
- * @hide
- */
-public class Decorator<T> implements InvocationHandler {
-
- public interface DecoratorListener {
- /**
- * This method is called before the target method is invoked
- * @param args arguments to target method
- * @param m Method being called
- */
- void onBeforeInvocation(Method m, Object[] args);
- /**
- * This function is called after the target method is invoked
- * if there were no uncaught exceptions
- * @param args arguments to target method
- * @param m Method being called
- * @param result return value of target method
- */
- void onAfterInvocation(Method m, Object[] args, Object result);
- /**
- * This method is called only if there was an exception thrown by the target method
- * during its invocation.
- *
- * @param args arguments to target method
- * @param m Method being called
- * @param t Throwable that was thrown
- * @return false to rethrow exception, true if the exception was handled
- */
- boolean onCatchException(Method m, Object[] args, Throwable t);
- /**
- * This is called after the target method is invoked, regardless of whether or not
- * there were any exceptions.
- * @param args arguments to target method
- * @param m Method being called
- */
- void onFinally(Method m, Object[] args);
- }
-
- private final T mObject;
- private final DecoratorListener mListener;
-
- /**
- * Create a decorator wrapping the specified object's method calls.
- *
- * @param obj the object whose method calls you want to intercept
- * @param listener the decorator handler for intercepted method calls
- * @param <T> the type of the element you want to wrap. This must be an interface.
- * @return a wrapped interface-compatible T
- */
- @SuppressWarnings("unchecked")
- public static<T> T newInstance(T obj, DecoratorListener listener) {
- return (T)java.lang.reflect.Proxy.newProxyInstance(
- obj.getClass().getClassLoader(),
- obj.getClass().getInterfaces(),
- new Decorator<T>(obj, listener));
- }
-
- private Decorator(T obj, DecoratorListener listener) {
- this.mObject = obj;
- this.mListener = listener;
- }
-
- @Override
- public Object invoke(Object proxy, Method m, Object[] args)
- throws Throwable
- {
- Object result = null;
- try {
- mListener.onBeforeInvocation(m, args);
- result = m.invoke(mObject, args);
- mListener.onAfterInvocation(m, args, result);
- } catch (InvocationTargetException e) {
- Throwable t = e.getTargetException();
- if (!mListener.onCatchException(m, args, t)) {
- throw t;
- }
- } finally {
- mListener.onFinally(m, args);
- }
- return result;
- }
-}
diff --git a/core/java/android/hardware/camera2/utils/SubmitInfo.java b/core/java/android/hardware/camera2/utils/SubmitInfo.java
new file mode 100644
index 0000000..d1692b5
--- /dev/null
+++ b/core/java/android/hardware/camera2/utils/SubmitInfo.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2015 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 android.hardware.camera2.utils;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.hardware.camera2.ICameraDeviceUser;
+
+/**
+ * The status information returned for a successful capture request submission.
+ *
+ * Includes the request ID for the newly submitted capture request, and the
+ * last frame number of either the previous repeating request (for repeating
+ * requests), or of the request(s) just submitted (for single-shot capture).
+ *
+ * @hide
+ */
+public class SubmitInfo implements Parcelable {
+
+ private int mRequestId;
+ private long mLastFrameNumber;
+
+ public SubmitInfo() {
+ mRequestId = -1;
+ mLastFrameNumber = ICameraDeviceUser.NO_IN_FLIGHT_REPEATING_FRAMES;
+ }
+
+ public SubmitInfo(int requestId, long lastFrameNumber) {
+ mRequestId = requestId;
+ mLastFrameNumber = lastFrameNumber;
+ }
+
+ public static final Parcelable.Creator<SubmitInfo> CREATOR =
+ new Parcelable.Creator<SubmitInfo>() {
+ @Override
+ public SubmitInfo createFromParcel(Parcel in) {
+ return new SubmitInfo(in);
+ }
+
+ @Override
+ public SubmitInfo[] newArray(int size) {
+ return new SubmitInfo[size];
+ }
+ };
+
+ private SubmitInfo(Parcel in) {
+ readFromParcel(in);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeInt(mRequestId);
+ dest.writeLong(mLastFrameNumber);
+ }
+
+ public void readFromParcel(Parcel in) {
+ mRequestId = in.readInt();
+ mLastFrameNumber = in.readLong();
+ }
+
+ /**
+ * Return the request ID for the submitted capture request/burst.
+ *
+ * This is used to track the completion status of the requested captures,
+ * and to cancel repeating requests.
+ */
+ public int getRequestId() {
+ return mRequestId;
+ }
+
+ /**
+ * Return the last frame number for the submitted capture request/burst.
+ *
+ * For a repeating request, this is the last frame number of the _prior_
+ * repeating request, to indicate when to fire the sequence completion callback
+ * for the prior repeating request.
+ *
+ * For a single-shot capture, this is the last frame number of _this_
+ * burst, to indicate when to fire the sequence completion callback for the request itself.
+ *
+ * For a repeating request, may be NO_IN_FLIGHT_REPEATING_FRAMES, if no
+ * instances of a prior repeating request were actually issued to the camera device.
+ */
+ public long getLastFrameNumber() {
+ return mLastFrameNumber;
+ }
+
+}
diff --git a/core/java/android/hardware/fingerprint/FingerprintManager.java b/core/java/android/hardware/fingerprint/FingerprintManager.java
index abd02f0..b8088f3 100644
--- a/core/java/android/hardware/fingerprint/FingerprintManager.java
+++ b/core/java/android/hardware/fingerprint/FingerprintManager.java
@@ -540,7 +540,7 @@
if (mService != null) try {
result = mService.preEnroll(mToken);
} catch (RemoteException e) {
- Log.w(TAG, "Remote exception in enroll: ", e);
+ throw e.rethrowFromSystemServer();
}
return result;
}
@@ -555,7 +555,7 @@
if (mService != null) try {
result = mService.postEnroll(mToken);
} catch (RemoteException e) {
- Log.w(TAG, "Remote exception in post enroll: ", e);
+ throw e.rethrowFromSystemServer();
}
return result;
}
@@ -571,7 +571,7 @@
if (mService != null) try {
mService.setActiveUser(userId);
} catch (RemoteException e) {
- Log.w(TAG, "Remote exception in setActiveUser: ", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -614,7 +614,7 @@
try {
mService.rename(fpId, userId, newName);
} catch (RemoteException e) {
- Log.v(TAG, "Remote exception in rename(): ", e);
+ throw e.rethrowFromSystemServer();
}
} else {
Log.w(TAG, "rename(): Service not connected!");
@@ -632,7 +632,7 @@
if (mService != null) try {
return mService.getEnrolledFingerprints(userId, mContext.getOpPackageName());
} catch (RemoteException e) {
- Log.v(TAG, "Remote exception in getEnrolledFingerprints: ", e);
+ throw e.rethrowFromSystemServer();
}
return null;
}
@@ -659,7 +659,7 @@
return mService.hasEnrolledFingerprints(
UserHandle.myUserId(), mContext.getOpPackageName());
} catch (RemoteException e) {
- Log.v(TAG, "Remote exception in getEnrolledFingerprints: ", e);
+ throw e.rethrowFromSystemServer();
}
return false;
}
@@ -674,7 +674,7 @@
if (mService != null) try {
return mService.hasEnrolledFingerprints(userId, mContext.getOpPackageName());
} catch (RemoteException e) {
- Log.v(TAG, "Remote exception in getEnrolledFingerprints: ", e);
+ throw e.rethrowFromSystemServer();
}
return false;
}
@@ -691,7 +691,7 @@
long deviceId = 0; /* TODO: plumb hardware id to FPMS */
return mService.isHardwareDetected(deviceId, mContext.getOpPackageName());
} catch (RemoteException e) {
- Log.v(TAG, "Remote exception in isFingerprintHardwareDetected(): ", e);
+ throw e.rethrowFromSystemServer();
}
} else {
Log.w(TAG, "isFingerprintHardwareDetected(): Service not connected!");
@@ -710,7 +710,7 @@
try {
return mService.getAuthenticatorId(mContext.getOpPackageName());
} catch (RemoteException e) {
- Log.v(TAG, "Remote exception in getAuthenticatorId(): ", e);
+ throw e.rethrowFromSystemServer();
}
} else {
Log.w(TAG, "getAuthenticatorId(): Service not connected!");
@@ -730,7 +730,7 @@
try {
mService.resetTimeout(token);
} catch (RemoteException e) {
- Log.v(TAG, "Remote exception in resetTimeout(): ", e);
+ throw e.rethrowFromSystemServer();
}
} else {
Log.w(TAG, "resetTimeout(): Service not connected!");
@@ -765,7 +765,7 @@
}
});
} catch (RemoteException e) {
- Log.v(TAG, "Remote exception in addLockoutResetCallback(): ", e);
+ throw e.rethrowFromSystemServer();
}
} else {
Log.w(TAG, "addLockoutResetCallback(): Service not connected!");
@@ -881,8 +881,7 @@
try {
return ActivityManagerNative.getDefault().getCurrentUser().id;
} catch (RemoteException e) {
- Log.w(TAG, "Failed to get current user id\n");
- return UserHandle.USER_NULL;
+ throw e.rethrowFromSystemServer();
}
}
@@ -890,7 +889,7 @@
if (mService != null) try {
mService.cancelEnrollment(mToken);
} catch (RemoteException e) {
- if (DEBUG) Log.w(TAG, "Remote exception while canceling enrollment");
+ throw e.rethrowFromSystemServer();
}
}
@@ -898,7 +897,7 @@
if (mService != null) try {
mService.cancelAuthentication(mToken, mContext.getOpPackageName());
} catch (RemoteException e) {
- if (DEBUG) Log.w(TAG, "Remote exception while canceling enrollment");
+ throw e.rethrowFromSystemServer();
}
}
diff --git a/core/java/android/hardware/hdmi/HdmiControlManager.java b/core/java/android/hardware/hdmi/HdmiControlManager.java
index 6effc0d..ff87b67 100644
--- a/core/java/android/hardware/hdmi/HdmiControlManager.java
+++ b/core/java/android/hardware/hdmi/HdmiControlManager.java
@@ -267,7 +267,7 @@
try {
types = mService.getSupportedTypes();
} catch (RemoteException e) {
- // Do nothing.
+ throw e.rethrowFromSystemServer();
}
}
mHasTvDevice = hasDeviceType(types, HdmiDeviceInfo.DEVICE_TV);
@@ -403,7 +403,7 @@
try {
mService.addHotplugEventListener(wrappedListener);
} catch (RemoteException e) {
- Log.e(TAG, "failed to add hotplug event listener: ", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -425,7 +425,7 @@
try {
mService.removeHotplugEventListener(wrappedListener);
} catch (RemoteException e) {
- Log.e(TAG, "failed to remove hotplug event listener: ", e);
+ throw e.rethrowFromSystemServer();
}
}
diff --git a/core/java/android/hardware/input/InputManager.java b/core/java/android/hardware/input/InputManager.java
index cbe3412..fbac58c 100644
--- a/core/java/android/hardware/input/InputManager.java
+++ b/core/java/android/hardware/input/InputManager.java
@@ -252,7 +252,7 @@
try {
inputDevice = mIm.getInputDevice(id);
} catch (RemoteException ex) {
- throw new RuntimeException("Could not get input device information.", ex);
+ throw ex.rethrowFromSystemServer();
}
if (inputDevice != null) {
mInputDevices.setValueAt(index, inputDevice);
@@ -284,7 +284,7 @@
try {
inputDevice = mIm.getInputDevice(id);
} catch (RemoteException ex) {
- // Ignore the problem for the purposes of this method.
+ throw ex.rethrowFromSystemServer();
}
if (inputDevice == null) {
continue;
@@ -384,8 +384,7 @@
try {
return mIm.isInTabletMode();
} catch (RemoteException ex) {
- Log.w(TAG, "Could not get tablet mode state", ex);
- return SWITCH_STATE_UNKNOWN;
+ throw ex.rethrowFromSystemServer();
}
}
@@ -439,7 +438,7 @@
try {
mIm.registerTabletModeChangedListener(listener);
} catch (RemoteException ex) {
- throw new RuntimeException("Could not register tablet mode changed listener", ex);
+ throw ex.rethrowFromSystemServer();
}
mTabletModeChangedListener = listener;
mOnTabletModeChangedListeners = new ArrayList<>();
@@ -471,8 +470,7 @@
try {
return mIm.getKeyboardLayouts();
} catch (RemoteException ex) {
- Log.w(TAG, "Could not get list of keyboard layout informations.", ex);
- return new KeyboardLayout[0];
+ throw ex.rethrowFromSystemServer();
}
}
@@ -494,8 +492,7 @@
try {
return mIm.getKeyboardLayoutsForInputDevice(identifier);
} catch (RemoteException ex) {
- Log.w(TAG, "Could not get list of keyboard layouts for input device.", ex);
- return new KeyboardLayout[0];
+ throw ex.rethrowFromSystemServer();
}
}
@@ -516,8 +513,7 @@
try {
return mIm.getKeyboardLayout(keyboardLayoutDescriptor);
} catch (RemoteException ex) {
- Log.w(TAG, "Could not get keyboard layout information.", ex);
- return null;
+ throw ex.rethrowFromSystemServer();
}
}
@@ -534,8 +530,7 @@
try {
return mIm.getCurrentKeyboardLayoutForInputDevice(identifier);
} catch (RemoteException ex) {
- Log.w(TAG, "Could not get current keyboard layout for input device.", ex);
- return null;
+ throw ex.rethrowFromSystemServer();
}
}
@@ -565,7 +560,7 @@
mIm.setCurrentKeyboardLayoutForInputDevice(identifier,
keyboardLayoutDescriptor);
} catch (RemoteException ex) {
- Log.w(TAG, "Could not set current keyboard layout for input device.", ex);
+ throw ex.rethrowFromSystemServer();
}
}
@@ -585,8 +580,7 @@
try {
return mIm.getEnabledKeyboardLayoutsForInputDevice(identifier);
} catch (RemoteException ex) {
- Log.w(TAG, "Could not get keyboard layouts for input device.", ex);
- return ArrayUtils.emptyArray(String.class);
+ throw ex.rethrowFromSystemServer();
}
}
@@ -614,7 +608,7 @@
try {
mIm.addKeyboardLayoutForInputDevice(identifier, keyboardLayoutDescriptor);
} catch (RemoteException ex) {
- Log.w(TAG, "Could not add keyboard layout for input device.", ex);
+ throw ex.rethrowFromSystemServer();
}
}
@@ -642,7 +636,7 @@
try {
mIm.removeKeyboardLayoutForInputDevice(identifier, keyboardLayoutDescriptor);
} catch (RemoteException ex) {
- Log.w(TAG, "Could not remove keyboard layout for input device.", ex);
+ throw ex.rethrowFromSystemServer();
}
}
@@ -664,8 +658,7 @@
return mIm.getKeyboardLayoutForInputDevice(
identifier, inputMethodInfo, inputMethodSubtype);
} catch (RemoteException ex) {
- Log.w(TAG, "Could not set keyboard layout.", ex);
- return null;
+ throw ex.rethrowFromSystemServer();
}
}
@@ -687,7 +680,7 @@
mIm.setKeyboardLayoutForInputDevice(identifier, inputMethodInfo,
inputMethodSubtype, keyboardLayoutDescriptor);
} catch (RemoteException ex) {
- Log.w(TAG, "Could not set keyboard layout.", ex);
+ throw ex.rethrowFromSystemServer();
}
}
@@ -704,8 +697,7 @@
try {
return mIm.getTouchCalibrationForInputDevice(inputDeviceDescriptor, surfaceRotation);
} catch (RemoteException ex) {
- Log.w(TAG, "Could not get calibration matrix for input device.", ex);
- return TouchCalibration.IDENTITY;
+ throw ex.rethrowFromSystemServer();
}
}
@@ -726,7 +718,7 @@
try {
mIm.setTouchCalibrationForInputDevice(inputDeviceDescriptor, surfaceRotation, calibration);
} catch (RemoteException ex) {
- Log.w(TAG, "Could not set calibration matrix for input device.", ex);
+ throw ex.rethrowFromSystemServer();
}
}
@@ -793,7 +785,7 @@
try {
mIm.tryPointerSpeed(speed);
} catch (RemoteException ex) {
- Log.w(TAG, "Could not set temporary pointer speed.", ex);
+ throw ex.rethrowFromSystemServer();
}
}
@@ -831,7 +823,7 @@
try {
mIm.hasKeys(id, InputDevice.SOURCE_ANY, keyCodes, ret);
} catch (RemoteException e) {
- // no fallback; just return the empty array
+ throw e.rethrowFromSystemServer();
}
return ret;
}
@@ -871,7 +863,7 @@
try {
return mIm.injectInputEvent(event, mode);
} catch (RemoteException ex) {
- return false;
+ throw ex.rethrowFromSystemServer();
}
}
@@ -887,7 +879,7 @@
try {
mIm.setPointerIconShape(iconId);
} catch (RemoteException ex) {
- // Do nothing.
+ throw ex.rethrowFromSystemServer();
}
}
@@ -896,7 +888,7 @@
try {
mIm.setCustomPointerIcon(icon);
} catch (RemoteException ex) {
- // Do nothing.
+ throw ex.rethrowFromSystemServer();
}
}
@@ -914,7 +906,7 @@
try {
mIm.setPointerIconDetached(detached);
} catch (RemoteException ex) {
- // Do nothing.
+ throw ex.rethrowFromSystemServer();
}
}
@@ -924,8 +916,7 @@
try {
mIm.registerInputDevicesChangedListener(listener);
} catch (RemoteException ex) {
- throw new RuntimeException(
- "Could not get register input device changed listener", ex);
+ throw ex.rethrowFromSystemServer();
}
mInputDevicesChangedListener = listener;
}
@@ -935,7 +926,7 @@
try {
ids = mIm.getInputDeviceIds();
} catch (RemoteException ex) {
- throw new RuntimeException("Could not get input device ids.", ex);
+ throw ex.rethrowFromSystemServer();
}
mInputDevices = new SparseArray<InputDevice>();
@@ -1175,7 +1166,7 @@
try {
mIm.vibrate(mDeviceId, pattern, repeat, mToken);
} catch (RemoteException ex) {
- Log.w(TAG, "Failed to vibrate.", ex);
+ throw ex.rethrowFromSystemServer();
}
}
@@ -1184,7 +1175,7 @@
try {
mIm.cancelVibrate(mDeviceId, mToken);
} catch (RemoteException ex) {
- Log.w(TAG, "Failed to cancel vibration.", ex);
+ throw ex.rethrowFromSystemServer();
}
}
}
diff --git a/core/java/android/hardware/soundtrigger/SoundTrigger.java b/core/java/android/hardware/soundtrigger/SoundTrigger.java
index cc2b764..b635088 100644
--- a/core/java/android/hardware/soundtrigger/SoundTrigger.java
+++ b/core/java/android/hardware/soundtrigger/SoundTrigger.java
@@ -689,12 +689,19 @@
return false;
if (triggerInData != other.triggerInData)
return false;
- if (captureFormat.getSampleRate() != other.captureFormat.getSampleRate())
- return false;
- if (captureFormat.getEncoding() != other.captureFormat.getEncoding())
- return false;
- if (captureFormat.getChannelMask() != other.captureFormat.getChannelMask())
- return false;
+ if (captureFormat == null) {
+ if (other.captureFormat != null)
+ return false;
+ } else {
+ if (other.captureFormat == null)
+ return false;
+ if (captureFormat.getSampleRate() != other.captureFormat.getSampleRate())
+ return false;
+ if (captureFormat.getEncoding() != other.captureFormat.getEncoding())
+ return false;
+ if (captureFormat.getChannelMask() != other.captureFormat.getChannelMask())
+ return false;
+ }
return true;
}
@@ -1002,10 +1009,10 @@
int encoding = in.readInt();
int channelMask = in.readInt();
captureFormat = (new AudioFormat.Builder())
- .setChannelMask(channelMask)
- .setEncoding(encoding)
- .setSampleRate(sampleRate)
- .build();
+ .setChannelMask(channelMask)
+ .setEncoding(encoding)
+ .setSampleRate(sampleRate)
+ .build();
}
byte[] data = in.readBlob();
KeyphraseRecognitionExtra[] keyphraseExtras =
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 7004e97..5f1043b 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -45,10 +45,12 @@
import android.telephony.SubscriptionManager;
import android.util.ArrayMap;
import android.util.Log;
+import android.util.SparseArray;
import com.android.internal.telephony.ITelephony;
import com.android.internal.telephony.PhoneConstants;
import com.android.internal.util.Protocol;
+import com.android.internal.util.MessageUtils;
import libcore.net.event.NetworkEventDispatcher;
@@ -79,6 +81,13 @@
public class ConnectivityManager {
private static final String TAG = "ConnectivityManager";
+ private static final SparseArray<String> sMagicDecoderRing = MessageUtils.findMessageNames(
+ new Class[]{ConnectivityManager.class}, new String[]{"CALLBACK_"});
+
+ private static final String whatToString(int what) {
+ return sMagicDecoderRing.get(what, Integer.toString(what));
+ }
+
/**
* A change in network connectivity has occurred. A default connection has either
* been established or lost. The NetworkInfo for the affected network is
@@ -733,7 +742,7 @@
try {
return mService.getActiveNetworkInfo();
} catch (RemoteException e) {
- return null;
+ throw e.rethrowFromSystemServer();
}
}
@@ -753,7 +762,7 @@
try {
return mService.getActiveNetwork();
} catch (RemoteException e) {
- return null;
+ throw e.rethrowFromSystemServer();
}
}
@@ -777,7 +786,7 @@
try {
return mService.setAlwaysOnVpnPackage(userId, vpnPackage);
} catch (RemoteException e) {
- return false;
+ throw e.rethrowFromSystemServer();
}
}
@@ -794,7 +803,7 @@
try {
return mService.getAlwaysOnVpnPackage(userId);
} catch (RemoteException e) {
- return null;
+ throw e.rethrowFromSystemServer();
}
}
@@ -815,7 +824,7 @@
try {
return mService.getActiveNetworkInfoForUid(uid);
} catch (RemoteException e) {
- return null;
+ throw e.rethrowFromSystemServer();
}
}
@@ -839,7 +848,7 @@
try {
return mService.getNetworkInfo(networkType);
} catch (RemoteException e) {
- return null;
+ throw e.rethrowFromSystemServer();
}
}
@@ -859,7 +868,7 @@
try {
return mService.getNetworkInfoForNetwork(network);
} catch (RemoteException e) {
- return null;
+ throw e.rethrowFromSystemServer();
}
}
@@ -880,7 +889,7 @@
try {
return mService.getAllNetworkInfo();
} catch (RemoteException e) {
- return null;
+ throw e.rethrowFromSystemServer();
}
}
@@ -900,7 +909,7 @@
try {
return mService.getNetworkForType(networkType);
} catch (RemoteException e) {
- return null;
+ throw e.rethrowFromSystemServer();
}
}
@@ -916,7 +925,7 @@
try {
return mService.getAllNetworks();
} catch (RemoteException e) {
- return null;
+ throw e.rethrowFromSystemServer();
}
}
@@ -929,7 +938,7 @@
try {
return mService.getDefaultNetworkCapabilitiesForUser(userId);
} catch (RemoteException e) {
- return null;
+ throw e.rethrowFromSystemServer();
}
}
@@ -948,7 +957,7 @@
try {
return mService.getActiveLinkProperties();
} catch (RemoteException e) {
- return null;
+ throw e.rethrowFromSystemServer();
}
}
@@ -972,7 +981,7 @@
try {
return mService.getLinkPropertiesForType(networkType);
} catch (RemoteException e) {
- return null;
+ throw e.rethrowFromSystemServer();
}
}
@@ -989,7 +998,7 @@
try {
return mService.getLinkProperties(network);
} catch (RemoteException e) {
- return null;
+ throw e.rethrowFromSystemServer();
}
}
@@ -1006,7 +1015,7 @@
try {
return mService.getNetworkCapabilities(network);
} catch (RemoteException e) {
- return null;
+ throw e.rethrowFromSystemServer();
}
}
@@ -1024,7 +1033,7 @@
try {
return mService.getCaptivePortalServerUrl();
} catch (RemoteException e) {
- return null;
+ throw e.rethrowFromSystemServer();
}
}
@@ -1324,7 +1333,9 @@
int type = legacyTypeForNetworkCapabilities(netCap);
try {
delay = mService.getRestoreDefaultNetworkDelay(type);
- } catch (RemoteException e) {}
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
LegacyRequest l = new LegacyRequest();
l.networkCapabilities = netCap;
l.delay = delay;
@@ -1542,7 +1553,7 @@
try {
return mService.requestRouteToHostAddress(networkType, hostAddress.getAddress());
} catch (RemoteException e) {
- return false;
+ throw e.rethrowFromSystemServer();
}
}
@@ -1598,7 +1609,7 @@
try {
return mService.getActiveNetworkQuotaInfo();
} catch (RemoteException e) {
- return null;
+ throw e.rethrowFromSystemServer();
}
}
@@ -1617,7 +1628,9 @@
Log.d("ConnectivityManager", "getMobileDataEnabled()- subId=" + subId
+ " retVal=" + retVal);
return retVal;
- } catch (RemoteException e) { }
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
}
Log.d("ConnectivityManager", "getMobileDataEnabled()- remote exception retVal=false");
return false;
@@ -1678,6 +1691,7 @@
getNetworkManagementService().registerNetworkActivityListener(rl);
mNetworkActivityListeners.put(l, rl);
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
@@ -1695,6 +1709,7 @@
try {
getNetworkManagementService().unregisterNetworkActivityListener(rl);
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
@@ -1710,8 +1725,8 @@
try {
return getNetworkManagementService().isNetworkActive();
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
- return false;
}
/**
@@ -1785,7 +1800,7 @@
try {
return mService.getTetherableIfaces();
} catch (RemoteException e) {
- return new String[0];
+ throw e.rethrowFromSystemServer();
}
}
@@ -1802,7 +1817,7 @@
try {
return mService.getTetheredIfaces();
} catch (RemoteException e) {
- return new String[0];
+ throw e.rethrowFromSystemServer();
}
}
@@ -1825,7 +1840,7 @@
try {
return mService.getTetheringErroredIfaces();
} catch (RemoteException e) {
- return new String[0];
+ throw e.rethrowFromSystemServer();
}
}
@@ -1839,7 +1854,7 @@
try {
return mService.getTetheredDhcpRanges();
} catch (RemoteException e) {
- return new String[0];
+ throw e.rethrowFromSystemServer();
}
}
@@ -1871,7 +1886,7 @@
try {
return mService.tether(iface);
} catch (RemoteException e) {
- return TETHER_ERROR_SERVICE_UNAVAIL;
+ throw e.rethrowFromSystemServer();
}
}
@@ -1897,7 +1912,7 @@
try {
return mService.untether(iface);
} catch (RemoteException e) {
- return TETHER_ERROR_SERVICE_UNAVAIL;
+ throw e.rethrowFromSystemServer();
}
}
@@ -1917,7 +1932,7 @@
try {
return mService.isTetheringSupported();
} catch (RemoteException e) {
- return false;
+ throw e.rethrowFromSystemServer();
}
}
@@ -2005,7 +2020,7 @@
try {
mService.stopTethering(type);
} catch (RemoteException e) {
- Log.e(TAG, "Exception trying to stop tethering.", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -2025,7 +2040,7 @@
try {
return mService.getTetherableUsbRegexs();
} catch (RemoteException e) {
- return new String[0];
+ throw e.rethrowFromSystemServer();
}
}
@@ -2045,7 +2060,7 @@
try {
return mService.getTetherableWifiRegexs();
} catch (RemoteException e) {
- return new String[0];
+ throw e.rethrowFromSystemServer();
}
}
@@ -2065,7 +2080,7 @@
try {
return mService.getTetherableBluetoothRegexs();
} catch (RemoteException e) {
- return new String[0];
+ throw e.rethrowFromSystemServer();
}
}
@@ -2090,7 +2105,7 @@
try {
return mService.setUsbTethering(enable);
} catch (RemoteException e) {
- return TETHER_ERROR_SERVICE_UNAVAIL;
+ throw e.rethrowFromSystemServer();
}
}
@@ -2135,7 +2150,7 @@
try {
return mService.getLastTetherError(iface);
} catch (RemoteException e) {
- return TETHER_ERROR_SERVICE_UNAVAIL;
+ throw e.rethrowFromSystemServer();
}
}
@@ -2153,6 +2168,7 @@
try {
mService.reportInetCondition(networkType, percentage);
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
@@ -2174,6 +2190,7 @@
mService.reportNetworkConnectivity(network, true);
mService.reportNetworkConnectivity(network, false);
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
@@ -2192,6 +2209,7 @@
try {
mService.reportNetworkConnectivity(network, hasConnectivity);
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
@@ -2211,6 +2229,7 @@
try {
mService.setGlobalProxy(p);
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
@@ -2225,7 +2244,7 @@
try {
return mService.getGlobalProxy();
} catch (RemoteException e) {
- return null;
+ throw e.rethrowFromSystemServer();
}
}
@@ -2247,7 +2266,7 @@
try {
return mService.getProxyForNetwork(network);
} catch (RemoteException e) {
- return null;
+ throw e.rethrowFromSystemServer();
}
}
@@ -2282,8 +2301,9 @@
public boolean isNetworkSupported(int networkType) {
try {
return mService.isNetworkSupported(networkType);
- } catch (RemoteException e) {}
- return false;
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
}
/**
@@ -2303,7 +2323,7 @@
try {
return mService.isActiveNetworkMetered();
} catch (RemoteException e) {
- return false;
+ throw e.rethrowFromSystemServer();
}
}
@@ -2320,7 +2340,7 @@
try {
return mService.updateLockdownVpn();
} catch (RemoteException e) {
- return false;
+ throw e.rethrowFromSystemServer();
}
}
@@ -2339,6 +2359,7 @@
try {
timeOutMs = mService.checkMobileProvisioning(suggestedTimeOutMs);
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
return timeOutMs;
}
@@ -2351,8 +2372,8 @@
try {
return mService.getMobileProvisioningUrl();
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
- return null;
}
/**
@@ -2369,6 +2390,7 @@
try {
mService.setProvisioningNotificationVisible(visible, networkType, action);
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
@@ -2385,6 +2407,7 @@
try {
mService.setAirplaneMode(enable);
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
@@ -2392,14 +2415,18 @@
public void registerNetworkFactory(Messenger messenger, String name) {
try {
mService.registerNetworkFactory(messenger, name);
- } catch (RemoteException e) { }
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
}
/** {@hide} */
public void unregisterNetworkFactory(Messenger messenger) {
try {
mService.unregisterNetworkFactory(messenger);
- } catch (RemoteException e) { }
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
}
/**
@@ -2412,7 +2439,7 @@
try {
return mService.registerNetworkAgent(messenger, ni, lp, nc, score, misc);
} catch (RemoteException e) {
- return NETID_UNSET;
+ throw e.rethrowFromSystemServer();
}
}
@@ -2563,9 +2590,11 @@
@Override
public void handleMessage(Message message) {
- if (DBG) Log.d(TAG, "CM callback handler got msg " + message.what);
NetworkRequest request = (NetworkRequest) getObject(message, NetworkRequest.class);
Network network = (Network) getObject(message, Network.class);
+ if (DBG) {
+ Log.d(TAG, whatToString(message.what) + " for network " + network);
+ }
switch (message.what) {
case CALLBACK_PRECHECK: {
NetworkCallback callback = getCallback(request, "PRECHECK");
@@ -2730,7 +2759,9 @@
sNetworkCallback.put(networkCallback.networkRequest, networkCallback);
}
}
- } catch (RemoteException e) {}
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
if (networkCallback.networkRequest == null) decCallbackHandlerRefCount();
return networkCallback.networkRequest;
}
@@ -2893,7 +2924,9 @@
checkPendingIntent(operation);
try {
mService.pendingRequestForNetwork(request.networkCapabilities, operation);
- } catch (RemoteException e) {}
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
}
/**
@@ -2911,7 +2944,9 @@
checkPendingIntent(operation);
try {
mService.releasePendingNetworkRequest(operation);
- } catch (RemoteException e) {}
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
}
private void checkPendingIntent(PendingIntent intent) {
@@ -2970,7 +3005,9 @@
checkPendingIntent(operation);
try {
mService.pendingListenForNetwork(request.networkCapabilities, operation);
- } catch (RemoteException e) {}
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
}
/**
@@ -2988,7 +3025,7 @@
try {
return mService.requestBandwidthUpdate(network);
} catch (RemoteException e) {
- return false;
+ throw e.rethrowFromSystemServer();
}
}
@@ -3008,7 +3045,9 @@
}
try {
mService.releaseNetworkRequest(networkCallback.networkRequest);
- } catch (RemoteException e) {}
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
}
/**
@@ -3044,7 +3083,9 @@
public void setAcceptUnvalidated(Network network, boolean accept, boolean always) {
try {
mService.setAcceptUnvalidated(network, accept, always);
- } catch (RemoteException e) {}
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
}
/**
@@ -3055,6 +3096,7 @@
try {
mService.factoryReset();
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
@@ -3262,7 +3304,7 @@
try {
return getNetworkPolicyManager().getRestrictBackgroundByCaller();
} catch (RemoteException e) {
- return RESTRICT_BACKGROUND_STATUS_DISABLED;
+ throw e.rethrowFromSystemServer();
}
}
}
diff --git a/core/java/android/net/EthernetManager.java b/core/java/android/net/EthernetManager.java
index f45737a..664b7b4 100644
--- a/core/java/android/net/EthernetManager.java
+++ b/core/java/android/net/EthernetManager.java
@@ -87,8 +87,8 @@
public IpConfiguration getConfiguration() {
try {
return mService.getConfiguration();
- } catch (NullPointerException | RemoteException e) {
- return new IpConfiguration();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
@@ -98,7 +98,8 @@
public void setConfiguration(IpConfiguration config) {
try {
mService.setConfiguration(config);
- } catch (NullPointerException | RemoteException e) {
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
@@ -109,8 +110,8 @@
public boolean isAvailable() {
try {
return mService.isAvailable();
- } catch (NullPointerException | RemoteException e) {
- return false;
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
@@ -127,7 +128,8 @@
if (mListeners.size() == 1) {
try {
mService.addListener(mServiceListener);
- } catch (NullPointerException | RemoteException e) {
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -145,7 +147,8 @@
if (mListeners.isEmpty()) {
try {
mService.removeListener(mServiceListener);
- } catch (NullPointerException | RemoteException e) {
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
}
diff --git a/core/java/android/net/NetworkAgent.java b/core/java/android/net/NetworkAgent.java
index 20c2168..9e360e1 100644
--- a/core/java/android/net/NetworkAgent.java
+++ b/core/java/android/net/NetworkAgent.java
@@ -200,6 +200,14 @@
*/
public static final int CMD_PREVENT_AUTOMATIC_RECONNECT = BASE + 15;
+ /**
+ * Sent by ConnectivityService to the NetworkAgent to install an APF program in the network
+ * chipset for use to filter packets.
+ *
+ * obj = byte[] containing the APF program bytecode.
+ */
+ public static final int CMD_PUSH_APF_PROGRAM = BASE + 16;
+
public NetworkAgent(Looper looper, Context context, String logTag, NetworkInfo ni,
NetworkCapabilities nc, LinkProperties lp, int score) {
this(looper, context, logTag, ni, nc, lp, score, null);
@@ -319,6 +327,10 @@
preventAutomaticReconnect();
break;
}
+ case CMD_PUSH_APF_PROGRAM: {
+ installPacketFilter((byte[]) msg.obj);
+ break;
+ }
}
}
@@ -494,6 +506,15 @@
protected void preventAutomaticReconnect() {
}
+ /**
+ * Install a packet filter.
+ * @param filter an APF program to filter incoming packets.
+ * @return {@code true} if filter successfully installed, {@code false} otherwise.
+ */
+ protected boolean installPacketFilter(byte[] filter) {
+ return false;
+ }
+
protected void log(String s) {
Log.d(LOG_TAG, "NetworkAgent: " + s);
}
diff --git a/core/java/android/net/NetworkMisc.java b/core/java/android/net/NetworkMisc.java
index 5511a24..748699e 100644
--- a/core/java/android/net/NetworkMisc.java
+++ b/core/java/android/net/NetworkMisc.java
@@ -56,6 +56,22 @@
*/
public String subscriberId;
+ /**
+ * Version of APF instruction set supported for packet filtering. 0 indicates no support for
+ * packet filtering using APF programs.
+ */
+ public int apfVersionSupported;
+
+ /**
+ * Maximum size of APF program allowed.
+ */
+ public int maximumApfProgramSize;
+
+ /**
+ * Format of packets passed to APF filter. Should be one of ARPHRD_*
+ */
+ public int apfPacketFormat;
+
public NetworkMisc() {
}
@@ -65,6 +81,9 @@
explicitlySelected = nm.explicitlySelected;
acceptUnvalidated = nm.acceptUnvalidated;
subscriberId = nm.subscriberId;
+ apfVersionSupported = nm.apfVersionSupported;
+ maximumApfProgramSize = nm.maximumApfProgramSize;
+ apfPacketFormat = nm.apfPacketFormat;
}
}
@@ -79,6 +98,9 @@
out.writeInt(explicitlySelected ? 1 : 0);
out.writeInt(acceptUnvalidated ? 1 : 0);
out.writeString(subscriberId);
+ out.writeInt(apfVersionSupported);
+ out.writeInt(maximumApfProgramSize);
+ out.writeInt(apfPacketFormat);
}
public static final Creator<NetworkMisc> CREATOR = new Creator<NetworkMisc>() {
@@ -89,6 +111,9 @@
networkMisc.explicitlySelected = in.readInt() != 0;
networkMisc.acceptUnvalidated = in.readInt() != 0;
networkMisc.subscriberId = in.readString();
+ networkMisc.apfVersionSupported = in.readInt();
+ networkMisc.maximumApfProgramSize = in.readInt();
+ networkMisc.apfPacketFormat = in.readInt();
return networkMisc;
}
diff --git a/core/java/android/net/NetworkPolicyManager.java b/core/java/android/net/NetworkPolicyManager.java
index 94de933..8738424 100644
--- a/core/java/android/net/NetworkPolicyManager.java
+++ b/core/java/android/net/NetworkPolicyManager.java
@@ -68,10 +68,12 @@
public static final int FIREWALL_CHAIN_NONE = 0;
public static final int FIREWALL_CHAIN_DOZABLE = 1;
public static final int FIREWALL_CHAIN_STANDBY = 2;
+ public static final int FIREWALL_CHAIN_POWERSAVE = 3;
public static final String FIREWALL_CHAIN_NAME_NONE = "none";
public static final String FIREWALL_CHAIN_NAME_DOZABLE = "dozable";
public static final String FIREWALL_CHAIN_NAME_STANDBY = "standby";
+ public static final String FIREWALL_CHAIN_NAME_POWERSAVE = "powersave";
private static final boolean ALLOW_PLATFORM_APP_POLICY = true;
diff --git a/core/java/android/net/NetworkScoreManager.java b/core/java/android/net/NetworkScoreManager.java
index b6fe68a..01c160f 100644
--- a/core/java/android/net/NetworkScoreManager.java
+++ b/core/java/android/net/NetworkScoreManager.java
@@ -166,7 +166,7 @@
try {
return mService.updateScores(networks);
} catch (RemoteException e) {
- return false;
+ throw e.rethrowFromSystemServer();
}
}
@@ -186,7 +186,7 @@
try {
return mService.clearScores();
} catch (RemoteException e) {
- return false;
+ throw e.rethrowFromSystemServer();
}
}
@@ -206,7 +206,7 @@
try {
return mService.setActiveScorer(packageName);
} catch (RemoteException e) {
- return false;
+ throw e.rethrowFromSystemServer();
}
}
@@ -221,6 +221,7 @@
try {
mService.disableScoring();
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
@@ -265,6 +266,7 @@
try {
mService.registerNetworkScoreCache(networkType, scoreCache);
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
}
diff --git a/core/java/android/net/NetworkUtils.java b/core/java/android/net/NetworkUtils.java
index c6d919f..555032d 100644
--- a/core/java/android/net/NetworkUtils.java
+++ b/core/java/android/net/NetworkUtils.java
@@ -62,6 +62,13 @@
public native static void attachDhcpFilter(FileDescriptor fd) throws SocketException;
/**
+ * Attaches a socket filter that accepts ICMP6 router advertisement packets to the given socket.
+ * @param fd the socket's {@link FileDescriptor}.
+ * @param packetType the hardware address type, one of ARPHRD_*.
+ */
+ public native static void attachRaFilter(FileDescriptor fd, int packetType) throws SocketException;
+
+ /**
* Binds the current process to the network designated by {@code netId}. All sockets created
* in the future (and not explicitly bound via a bound {@link SocketFactory} (see
* {@link Network#getSocketFactory}) will be bound to this network. Note that if this
diff --git a/core/java/android/net/nsd/NsdManager.java b/core/java/android/net/nsd/NsdManager.java
index 377ed88..86bd502 100644
--- a/core/java/android/net/nsd/NsdManager.java
+++ b/core/java/android/net/nsd/NsdManager.java
@@ -619,7 +619,9 @@
public void setEnabled(boolean enabled) {
try {
mService.setEnabled(enabled);
- } catch (RemoteException e) { }
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
}
/**
@@ -632,7 +634,7 @@
try {
return mService.getMessenger();
} catch (RemoteException e) {
- return null;
+ throw e.rethrowFromSystemServer();
}
}
}
diff --git a/core/java/android/os/BatteryManager.java b/core/java/android/os/BatteryManager.java
index 56cb250..e40ebf7 100644
--- a/core/java/android/os/BatteryManager.java
+++ b/core/java/android/os/BatteryManager.java
@@ -221,7 +221,7 @@
try {
return mBatteryStats.isCharging();
} catch (RemoteException e) {
- return true;
+ throw e.rethrowFromSystemServer();
}
}
@@ -246,7 +246,7 @@
else
ret = Long.MIN_VALUE;
} catch (RemoteException e) {
- ret = Long.MIN_VALUE;
+ throw e.rethrowFromSystemServer();
}
return ret;
diff --git a/core/java/android/os/HardwarePropertiesManager.java b/core/java/android/os/HardwarePropertiesManager.java
index f48306a..9ca1dcd 100644
--- a/core/java/android/os/HardwarePropertiesManager.java
+++ b/core/java/android/os/HardwarePropertiesManager.java
@@ -79,8 +79,7 @@
try {
return mService.getDeviceTemperatures(mContext.getOpPackageName(), type);
} catch (RemoteException e) {
- Log.w(TAG, "Could not get device temperatures", e);
- return new float[0];
+ throw e.rethrowFromSystemServer();
}
default:
Log.w(TAG, "Unknown device temperature type.");
@@ -100,8 +99,7 @@
try {
return mService.getCpuUsages(mContext.getOpPackageName());
} catch (RemoteException e) {
- Log.w(TAG, "Could not get CPU usages", e);
- return new CpuUsageInfo[0];
+ throw e.rethrowFromSystemServer();
}
}
@@ -117,8 +115,7 @@
try {
return mService.getFanSpeeds(mContext.getOpPackageName());
} catch (RemoteException e) {
- Log.w(TAG, "Could not get fan speeds", e);
- return new float[0];
+ throw e.rethrowFromSystemServer();
}
}
}
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index 369ec15..2a4507c 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -620,6 +620,7 @@
try {
mService.userActivity(when, event, flags);
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
@@ -671,6 +672,7 @@
try {
mService.goToSleep(time, reason, flags);
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
@@ -697,6 +699,7 @@
try {
mService.wakeUp(time, "wakeUp", mContext.getOpPackageName());
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
@@ -707,6 +710,7 @@
try {
mService.wakeUp(time, reason, mContext.getOpPackageName());
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
@@ -735,6 +739,7 @@
try {
mService.nap(time);
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
@@ -757,6 +762,7 @@
try {
mService.boostScreenBrightness(time);
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
@@ -772,7 +778,7 @@
try {
return mService.isScreenBrightnessBoosted();
} catch (RemoteException e) {
- return false;
+ throw e.rethrowFromSystemServer();
}
}
@@ -790,6 +796,7 @@
try {
mService.setTemporaryScreenBrightnessSettingOverride(brightness);
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
@@ -803,7 +810,7 @@
try {
return mService.isWakeLockLevelSupported(level);
} catch (RemoteException e) {
- return false;
+ throw e.rethrowFromSystemServer();
}
}
@@ -867,7 +874,7 @@
try {
return mService.isInteractive();
} catch (RemoteException e) {
- return false;
+ throw e.rethrowFromSystemServer();
}
}
@@ -884,6 +891,7 @@
try {
mService.reboot(false, reason, true);
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
@@ -899,7 +907,7 @@
try {
return mService.isPowerSaveMode();
} catch (RemoteException e) {
- return false;
+ throw e.rethrowFromSystemServer();
}
}
@@ -916,7 +924,7 @@
try {
return mService.setPowerSaveMode(mode);
} catch (RemoteException e) {
- return false;
+ throw e.rethrowFromSystemServer();
}
}
@@ -936,7 +944,7 @@
try {
return mService.isDeviceIdleMode();
} catch (RemoteException e) {
- return false;
+ throw e.rethrowFromSystemServer();
}
}
@@ -956,7 +964,7 @@
try {
return mService.isLightDeviceIdleMode();
} catch (RemoteException e) {
- return false;
+ throw e.rethrowFromSystemServer();
}
}
@@ -975,7 +983,7 @@
try {
return mIDeviceIdleController.isPowerSaveWhitelistApp(packageName);
} catch (RemoteException e) {
- return false;
+ throw e.rethrowFromSystemServer();
}
}
@@ -992,6 +1000,7 @@
try {
mService.shutdown(confirm, reason, wait);
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
@@ -1118,6 +1127,7 @@
try {
mService.releaseWakeLock(mToken, 0);
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -1186,6 +1196,7 @@
mService.acquireWakeLock(mToken, mFlags, mTag, mPackageName, mWorkSource,
mHistoryTag);
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
mHeld = true;
}
@@ -1224,6 +1235,7 @@
try {
mService.releaseWakeLock(mToken, flags);
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
mHeld = false;
}
@@ -1280,6 +1292,7 @@
try {
mService.updateWakeLockWorkSource(mToken, mWorkSource, mHistoryTag);
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
}
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index 9984755..8fd3b0c 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -383,6 +383,9 @@
public static final int SIGNAL_KILL = 9;
public static final int SIGNAL_USR1 = 10;
+ private static long sStartElapsedRealtime;
+ private static long sStartUptimeMillis;
+
/**
* State for communicating with the zygote process.
*
@@ -772,6 +775,26 @@
public static final native long getElapsedCpuTime();
/**
+ * Return the {@link SystemClock#elapsedRealtime()} at which this process was started.
+ */
+ public static final long getStartElapsedRealtime() {
+ return sStartElapsedRealtime;
+ }
+
+ /**
+ * Return the {@link SystemClock#uptimeMillis()} at which this process was started.
+ */
+ public static final long getStartUptimeMillis() {
+ return sStartUptimeMillis;
+ }
+
+ /** @hide */
+ public static final void setStartTimes(long elapsedRealtime, long uptimeMillis) {
+ sStartElapsedRealtime = elapsedRealtime;
+ sStartUptimeMillis = uptimeMillis;
+ }
+
+ /**
* Returns true if the current process is a 64-bit runtime.
*/
public static final boolean is64Bit() {
diff --git a/core/java/android/os/ServiceSpecificException.java b/core/java/android/os/ServiceSpecificException.java
index 20f237a5..04fca19 100644
--- a/core/java/android/os/ServiceSpecificException.java
+++ b/core/java/android/os/ServiceSpecificException.java
@@ -20,20 +20,23 @@
*
* <p>This exception includes an error code specific to the throwing
* service. This is mostly used by system services to indicate
- * domain specific error conditions.
+ * domain specific error conditions.</p>
+ *
+ * <p>Since these exceptions are designed to be passed through Binder
+ * interfaces, and to be generated by native-code Binder services,
+ * they do not support exception chaining.</p>
*
* @hide
*/
public class ServiceSpecificException extends RuntimeException {
public final int errorCode;
- ServiceSpecificException(int errorCode, String message) {
+ public ServiceSpecificException(int errorCode, String message) {
super(message);
this.errorCode = errorCode;
}
- ServiceSpecificException(int errorCode) {
+ public ServiceSpecificException(int errorCode) {
this.errorCode = errorCode;
}
}
-
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 20b3798..7223dfb 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -36,6 +36,7 @@
import android.graphics.drawable.Drawable;
import android.os.storage.StorageManager;
import android.provider.Settings;
+import android.telephony.TelephonyManager;
import android.view.WindowManager.LayoutParams;
import com.android.internal.R;
@@ -680,6 +681,22 @@
}
/**
+ * Returns whether switching users is currently allowed.
+ * <p>For instance switching users is not allowed if the current user is in a phone call,
+ * or system user hasn't been unlocked yet
+ * @hide
+ */
+ public boolean canSwitchUsers() {
+ boolean allowUserSwitchingWhenSystemUserLocked = Settings.Global.getInt(
+ mContext.getContentResolver(),
+ Settings.Global.ALLOW_USER_SWITCHING_WHEN_SYSTEM_USER_LOCKED, 0) != 0;
+ boolean isSystemUserUnlocked = isUserUnlocked(UserHandle.SYSTEM);
+ boolean inCall = TelephonyManager.getDefault().getCallState()
+ != TelephonyManager.CALL_STATE_IDLE;
+ return (allowUserSwitchingWhenSystemUserLocked || isSystemUserUnlocked) && !inCall;
+ }
+
+ /**
* Returns the user handle for the user that this process is running under.
*
* @return the user handle of this process.
@@ -1641,7 +1658,7 @@
* android.graphics.drawable.Drawable, UserHandle, android.graphics.Rect, int)}.
* <p>
* If the original drawable is a BitmapDrawable and the backing bitmap is
- * mutable as per {@link android.graphics.Bitmap#isMutable()}, the bading
+ * mutable as per {@link android.graphics.Bitmap#isMutable()}, the badging
* is performed in place and the original drawable is returned.
* </p>
*
@@ -1664,17 +1681,17 @@
* badge to be used.
* <p>
* If the original drawable is a BitmapDrawable and the backing bitmap is
- * mutable as per {@link android.graphics.Bitmap#isMutable()}, the bading
+ * mutable as per {@link android.graphics.Bitmap#isMutable()}, the badging
* is performed in place and the original drawable is returned.
* </p>
*
* @param badgedDrawable The drawable to badge.
* @param user The target user.
* @param badgeLocation Where in the bounds of the badged drawable to place
- * the badge. If not provided, the badge is applied on top of the entire
+ * the badge. If it's {@code null}, the badge is applied on top of the entire
* drawable being badged.
* @param badgeDensity The optional desired density for the badge as per
- * {@link android.util.DisplayMetrics#densityDpi}. If not provided,
+ * {@link android.util.DisplayMetrics#densityDpi}. If it's not positive,
* the density of the display is used.
* @return A drawable that combines the original drawable and a badge as
* determined by the system.
diff --git a/core/java/android/os/storage/VolumeInfo.java b/core/java/android/os/storage/VolumeInfo.java
index 4b70649..ea0597d 100644
--- a/core/java/android/os/storage/VolumeInfo.java
+++ b/core/java/android/os/storage/VolumeInfo.java
@@ -438,10 +438,6 @@
final Intent intent = new Intent(DocumentsContract.ACTION_BROWSE);
intent.addCategory(Intent.CATEGORY_DEFAULT);
intent.setData(uri);
-
- // note that docsui treats this as *force* show advanced. So sending
- // false permits advanced to be shown based on user preferences.
- intent.putExtra(DocumentsContract.EXTRA_SHOW_ADVANCED, isPrimary());
intent.putExtra(DocumentsContract.EXTRA_SHOW_FILESIZE, true);
return intent;
}
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index 904b393..4b43f53 100644
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -8763,6 +8763,15 @@
* <li><em>Note: Some apps may choose to use phone number as the unique contact ID in DATA1.
* If this applies to you and you’d like phone number to be shown below the Contact Name by
* the Voice Assistant, then you may choose to leave DATA3 empty.</em></li>
+ * <li><em>Note: If your app also uses DATA3 to display contact details in the Contacts App,
+ * make sure it does not include prefix text such as "Message +<phone>" or "Free Message
+ * +<phone>", etc. If you must show the prefix text in the Contacts App, please use a
+ * different DATA# column, and update your contacts.xml to point to this new column. </em>
+ * </li>
+ * <li>Everytime the user sends a message to a contact, your app may choose to update the
+ * {@link ContactOptionsColumns#TIMES_CONTACTED} entry through DataUsageFeedback class.
+ * Doing this will allow Voice Assistant to bias speech recognition to contacts frequently
+ * contacted, this is particularly useful for contact names that are hard to pronounce.</li>
* </ul>
* <p>
* Input: {@link android.content.Intent#getType} is the MIME type of the data being sent.
diff --git a/core/java/android/provider/DocumentsContract.java b/core/java/android/provider/DocumentsContract.java
index 3700098..03a1ca6 100644
--- a/core/java/android/provider/DocumentsContract.java
+++ b/core/java/android/provider/DocumentsContract.java
@@ -93,9 +93,6 @@
public static final String EXTRA_PACKAGE_NAME = "android.content.extra.PACKAGE_NAME";
/** {@hide} */
- public static final String EXTRA_SHOW_ADVANCED = "android.content.extra.SHOW_ADVANCED";
-
- /** {@hide} */
public static final String EXTRA_SHOW_FILESIZE = "android.content.extra.SHOW_FILESIZE";
/** {@hide} */
@@ -564,22 +561,29 @@
public static final int FLAG_EMPTY = 1 << 16;
/**
- * Flag indicating that this root should only be visible to advanced
- * users.
- *
- * @see #COLUMN_FLAGS
- * @hide
- */
- public static final int FLAG_ADVANCED = 1 << 17;
-
- /**
* Flag indicating that this root has settings.
*
* @see #COLUMN_FLAGS
* @see DocumentsContract#ACTION_DOCUMENT_ROOT_SETTINGS
* @hide
*/
- public static final int FLAG_HAS_SETTINGS = 1 << 18;
+ public static final int FLAG_HAS_SETTINGS = 1 << 17;
+
+ /**
+ * Flag indicating that this root is on removable SD card storage.
+ *
+ * @see #COLUMN_FLAGS
+ * @hide
+ */
+ public static final int FLAG_REMOVABLE_SD = 1 << 18;
+
+ /**
+ * Flag indicating that this root is on removable USB storage.
+ *
+ * @see #COLUMN_FLAGS
+ * @hide
+ */
+ public static final int FLAG_REMOVABLE_USB = 1 << 19;
}
/**
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index cb45deb..f13f242 100755
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -4522,6 +4522,13 @@
public static final String USER_SETUP_COMPLETE = "user_setup_complete";
/**
+ * Prefix for category name that marks whether a suggested action from that category was
+ * completed.
+ * @hide
+ */
+ public static final String COMPLETED_CATEGORY_PREFIX = "suggested.completed_category.";
+
+ /**
* List of input methods that are currently enabled. This is a string
* containing the IDs of all enabled input methods, each ID separated
* by ':'.
diff --git a/core/java/android/service/carrier/CarrierMessagingService.java b/core/java/android/service/carrier/CarrierMessagingService.java
index f5396a3..140341c 100644
--- a/core/java/android/service/carrier/CarrierMessagingService.java
+++ b/core/java/android/service/carrier/CarrierMessagingService.java
@@ -51,6 +51,30 @@
= "android.service.carrier.CarrierMessagingService";
/**
+ * The default bitmask value passed to the callback of {@link #onReceiveTextSms} with all
+ * {@code RECEIVE_OPTIONS_x} flags cleared to indicate that the message should be kept and a
+ * new message notification should be shown.
+ *
+ * @see #RECEIVE_OPTIONS_DROP
+ * @see #RECEIVE_OPTIONS_SKIP_NOTIFY_WHEN_CREDENTIAL_ENCRYPTED_STORAGE_UNAVAILABLE
+ */
+ public static final int RECEIVE_OPTIONS_DEFAULT = 0;
+
+ /**
+ * Used to set the flag in the bitmask passed to the callback of {@link #onReceiveTextSms} to
+ * indicate that the inbound SMS should be dropped.
+ */
+ public static final int RECEIVE_OPTIONS_DROP = 0x1;
+
+ /**
+ * Used to set the flag in the bitmask passed to the callback of {@link #onReceiveTextSms} to
+ * indicate that a new message notification should not be shown to the user when the
+ * credential-encrypted storage of the device is not available before the user unlocks the
+ * phone. It is only applicable to devices that support file-based encryption.
+ */
+ public static final int RECEIVE_OPTIONS_SKIP_NOTIFY_WHEN_CREDENTIAL_ENCRYPTED_STORAGE_UNAVAILABLE = 0x2;
+
+ /**
* Indicates that an SMS or MMS message was successfully sent.
*/
public static final int SEND_STATUS_OK = 0;
@@ -96,7 +120,9 @@
* @param subId SMS subscription ID of the SIM
* @param callback result callback. Call with {@code true} to keep an inbound SMS message and
* deliver to SMS apps, and {@code false} to drop the message.
+ * @deprecated Use {@link #onReceiveTextSms} instead.
*/
+ @Deprecated
public void onFilterSms(@NonNull MessagePdu pdu, @NonNull String format, int destPort,
int subId, @NonNull ResultCallback<Boolean> callback) {
// optional
@@ -107,6 +133,36 @@
}
/**
+ * Override this method to filter inbound SMS messages.
+ *
+ * <p>This method will be called once for every incoming text SMS. You can invoke the callback
+ * with a bitmask to tell the platform how to handle the SMS. For a SMS received on a
+ * file-based encryption capable device while the credential-encrypted storage is not available,
+ * this method will be called for the second time when the credential-encrypted storage becomes
+ * available after the user unlocks the phone, if the bit {@link #RECEIVE_OPTIONS_DROP} is not
+ * set when invoking the callback.
+ *
+ * @param pdu the PDUs of the message
+ * @param format the format of the PDUs, typically "3gpp" or "3gpp2"
+ * @param destPort the destination port of a binary SMS, this will be -1 for text SMS
+ * @param subId SMS subscription ID of the SIM
+ * @param callback result callback. Call with a bitmask integer to indicate how the incoming
+ * text SMS should be handled by the platform. Use {@link #RECEIVE_OPTIONS_DROP} and
+ * {@link #RECEIVE_OPTIONS_SKIP_NOTIFY_WHEN_CREDENTIAL_ENCRYPTED_STORAGE_UNAVAILABLE}
+ * to set the flags in the bitmask.
+ */
+ public void onReceiveTextSms(@NonNull MessagePdu pdu, @NonNull String format,
+ int destPort, int subId, @NonNull final ResultCallback<Integer> callback) {
+ onFilterSms(pdu, format, destPort, subId, new ResultCallback<Boolean>() {
+ @Override
+ public void onReceiveResult(Boolean result) throws RemoteException {
+ callback.onReceiveResult(result ? RECEIVE_OPTIONS_DEFAULT : RECEIVE_OPTIONS_DROP
+ | RECEIVE_OPTIONS_SKIP_NOTIFY_WHEN_CREDENTIAL_ENCRYPTED_STORAGE_UNAVAILABLE);
+ }
+ });
+ }
+
+ /**
* Override this method to intercept text SMSs sent from the device.
* @deprecated Override {@link #onSendTextSms} below instead.
*
@@ -408,10 +464,11 @@
@Override
public void filterSms(MessagePdu pdu, String format, int destPort,
int subId, final ICarrierMessagingCallback callback) {
- onFilterSms(pdu, format, destPort, subId, new ResultCallback<Boolean>() {
+ onReceiveTextSms(pdu, format, destPort, subId,
+ new ResultCallback<Integer>() {
@Override
- public void onReceiveResult(final Boolean result) throws RemoteException {
- callback.onFilterComplete(result);
+ public void onReceiveResult(Integer options) throws RemoteException {
+ callback.onFilterComplete(options);
}
});
}
diff --git a/core/java/android/service/carrier/ICarrierMessagingCallback.aidl b/core/java/android/service/carrier/ICarrierMessagingCallback.aidl
index 6118a20..2753669 100644
--- a/core/java/android/service/carrier/ICarrierMessagingCallback.aidl
+++ b/core/java/android/service/carrier/ICarrierMessagingCallback.aidl
@@ -22,7 +22,7 @@
* @hide
*/
oneway interface ICarrierMessagingCallback {
- void onFilterComplete(boolean keepMessage);
+ void onFilterComplete(int result);
void onSendSmsComplete(int result, int messageRef);
void onSendMultipartSmsComplete(int result, in int[] messageRefs);
void onSendMmsComplete(int result, in byte[] sendConfPdu);
diff --git a/core/java/android/text/method/BaseKeyListener.java b/core/java/android/text/method/BaseKeyListener.java
index e79dfca..3564e11 100644
--- a/core/java/android/text/method/BaseKeyListener.java
+++ b/core/java/android/text/method/BaseKeyListener.java
@@ -16,6 +16,7 @@
package android.text.method;
+import android.graphics.Paint;
import android.icu.lang.UCharacter;
import android.icu.lang.UProperty;
import android.view.KeyEvent;
@@ -25,6 +26,8 @@
import android.text.style.ReplacementSpan;
import android.widget.TextView;
+import com.android.internal.annotations.GuardedBy;
+
import java.text.BreakIterator;
import java.util.Arrays;
import java.util.Collections;
@@ -45,6 +48,11 @@
implements KeyListener {
/* package */ static final Object OLD_SEL_START = new NoCopySpan.Concrete();
+ private final Object mLock = new Object();
+
+ @GuardedBy("mLock")
+ static Paint sCachedPaint = null;
+
/**
* Performs the action that happens when you press the {@link KeyEvent#KEYCODE_DEL} key in
* a {@link TextView}. If there is a selection, deletes the selection; otherwise,
@@ -258,20 +266,15 @@
}
// Returns the end offset to be deleted by a forward delete key from the given offset.
- private static int getOffsetForForwardDeleteKey(CharSequence text, int offset) {
+ private static int getOffsetForForwardDeleteKey(CharSequence text, int offset, Paint paint) {
final int len = text.length();
if (offset >= len - 1) {
return len;
}
- int codePoint = Character.codePointAt(text, offset);
- offset += Character.charCount(codePoint);
- if (offset == len) {
- return len;
- }
-
- // TODO: Handle emoji, combining chars, etc.
+ offset = paint.getTextRunCursor(text, offset, len, Paint.DIRECTION_LTR /* not used */,
+ offset, Paint.CURSOR_AFTER);
return adjustReplacementSpan(text, offset, false /* move to the end */);
}
@@ -311,7 +314,18 @@
final int start = Selection.getSelectionEnd(content);
final int end;
if (isForwardDelete) {
- end = getOffsetForForwardDeleteKey(content, start);
+ final Paint paint;
+ if (view instanceof TextView) {
+ paint = ((TextView)view).getPaint();
+ } else {
+ synchronized (mLock) {
+ if (sCachedPaint == null) {
+ sCachedPaint = new Paint();
+ }
+ paint = sCachedPaint;
+ }
+ }
+ end = getOffsetForForwardDeleteKey(content, start, paint);
} else {
end = getOffsetForBackspaceKey(content, start);
}
diff --git a/core/java/android/text/util/Linkify.java b/core/java/android/text/util/Linkify.java
index fbd9924..bd376ea 100644
--- a/core/java/android/text/util/Linkify.java
+++ b/core/java/android/text/util/Linkify.java
@@ -224,7 +224,7 @@
}
if ((mask & EMAIL_ADDRESSES) != 0) {
- gatherLinks(links, text, Patterns.EMAIL_ADDRESS,
+ gatherLinks(links, text, Patterns.AUTOLINK_EMAIL_ADDRESS,
new String[] { "mailto:" },
null, null);
}
diff --git a/core/java/android/util/ArrayMap.java b/core/java/android/util/ArrayMap.java
index bdb1fdc..92a5803 100644
--- a/core/java/android/util/ArrayMap.java
+++ b/core/java/android/util/ArrayMap.java
@@ -67,7 +67,7 @@
/**
* @hide Special immutable empty ArrayMap.
*/
- public static final ArrayMap EMPTY = new ArrayMap(true);
+ public static final ArrayMap EMPTY = new ArrayMap<>(-1);
/**
* Caches of small array objects to avoid spamming garbage. The cache
@@ -80,6 +80,7 @@
static Object[] mTwiceBaseCache;
static int mTwiceBaseCacheSize;
+ final boolean mIdentityHashCode;
int[] mHashes;
Object[] mArray;
int mSize;
@@ -236,16 +237,27 @@
* will grow once items are added to it.
*/
public ArrayMap() {
- mHashes = EmptyArray.INT;
- mArray = EmptyArray.OBJECT;
- mSize = 0;
+ this(0, false);
}
/**
* Create a new ArrayMap with a given initial capacity.
*/
public ArrayMap(int capacity) {
- if (capacity == 0) {
+ this(capacity, false);
+ }
+
+ /** {@hide} */
+ public ArrayMap(int capacity, boolean identityHashCode) {
+ mIdentityHashCode = identityHashCode;
+
+ // If this is immutable, use the sentinal EMPTY_IMMUTABLE_INTS
+ // instance instead of the usual EmptyArray.INT. The reference
+ // is checked later to see if the array is allowed to grow.
+ if (capacity < 0) {
+ mHashes = EMPTY_IMMUTABLE_INTS;
+ mArray = EmptyArray.OBJECT;
+ } else if (capacity == 0) {
mHashes = EmptyArray.INT;
mArray = EmptyArray.OBJECT;
} else {
@@ -254,15 +266,6 @@
mSize = 0;
}
- private ArrayMap(boolean immutable) {
- // If this is immutable, use the sentinal EMPTY_IMMUTABLE_INTS
- // instance instead of the usual EmptyArray.INT. The reference
- // is checked later to see if the array is allowed to grow.
- mHashes = immutable ? EMPTY_IMMUTABLE_INTS : EmptyArray.INT;
- mArray = EmptyArray.OBJECT;
- mSize = 0;
- }
-
/**
* Create a new ArrayMap with the mappings from the given ArrayMap.
*/
@@ -336,7 +339,8 @@
* @return Returns the index of the key if it exists, else a negative integer.
*/
public int indexOfKey(Object key) {
- return key == null ? indexOfNull() : indexOf(key, key.hashCode());
+ return key == null ? indexOfNull()
+ : indexOf(key, mIdentityHashCode ? System.identityHashCode(key) : key.hashCode());
}
int indexOfValue(Object value) {
@@ -437,7 +441,7 @@
hash = 0;
index = indexOfNull();
} else {
- hash = key.hashCode();
+ hash = mIdentityHashCode ? System.identityHashCode(key) : key.hashCode();
index = indexOf(key, hash);
}
if (index >= 0) {
@@ -488,7 +492,8 @@
*/
public void append(K key, V value) {
int index = mSize;
- final int hash = key == null ? 0 : key.hashCode();
+ final int hash = key == null ? 0
+ : (mIdentityHashCode ? System.identityHashCode(key) : key.hashCode());
if (index >= mHashes.length) {
throw new IllegalStateException("Array is full");
}
diff --git a/core/java/android/util/ArraySet.java b/core/java/android/util/ArraySet.java
index b7a3c42..9e9314f 100644
--- a/core/java/android/util/ArraySet.java
+++ b/core/java/android/util/ArraySet.java
@@ -69,6 +69,7 @@
static Object[] mTwiceBaseCache;
static int mTwiceBaseCacheSize;
+ final boolean mIdentityHashCode;
int[] mHashes;
Object[] mArray;
int mSize;
@@ -222,15 +223,19 @@
* will grow once items are added to it.
*/
public ArraySet() {
- mHashes = EmptyArray.INT;
- mArray = EmptyArray.OBJECT;
- mSize = 0;
+ this(0, false);
}
/**
* Create a new ArraySet with a given initial capacity.
*/
public ArraySet(int capacity) {
+ this(capacity, false);
+ }
+
+ /** {@hide} */
+ public ArraySet(int capacity, boolean identityHashCode) {
+ mIdentityHashCode = identityHashCode;
if (capacity == 0) {
mHashes = EmptyArray.INT;
mArray = EmptyArray.OBJECT;
@@ -306,7 +311,8 @@
* @return Returns the index of the value if it exists, else a negative integer.
*/
public int indexOf(Object key) {
- return key == null ? indexOfNull() : indexOf(key, key.hashCode());
+ return key == null ? indexOfNull()
+ : indexOf(key, mIdentityHashCode ? System.identityHashCode(key) : key.hashCode());
}
/**
@@ -343,7 +349,7 @@
hash = 0;
index = indexOfNull();
} else {
- hash = value.hashCode();
+ hash = mIdentityHashCode ? System.identityHashCode(value) : value.hashCode();
index = indexOf(value, hash);
}
if (index >= 0) {
diff --git a/core/java/android/util/LocaleList.java b/core/java/android/util/LocaleList.java
index fc39004..fa3921c 100644
--- a/core/java/android/util/LocaleList.java
+++ b/core/java/android/util/LocaleList.java
@@ -478,8 +478,6 @@
/**
* Returns the default locale list, adjusted by moving the default locale to its first
* position.
- *
- * {@hide}
*/
@NonNull @Size(min=1)
public static LocaleList getAdjustedDefault() {
diff --git a/core/java/android/util/Patterns.java b/core/java/android/util/Patterns.java
index 9f2bcfd..9ed4850 100644
--- a/core/java/android/util/Patterns.java
+++ b/core/java/android/util/Patterns.java
@@ -394,6 +394,36 @@
public static final Pattern AUTOLINK_WEB_URL = Pattern.compile(
"(" + WEB_URL_WITH_PROTOCOL + "|" + WEB_URL_WITHOUT_PROTOCOL + ")");
+ /**
+ * Regular expression for valid email characters. Does not include some of the valid characters
+ * defined in RFC5321: #&~!^`{}/=$*?|
+ */
+ private static final String EMAIL_CHAR = LABEL_CHAR + "\\+\\-_%'";
+
+ /**
+ * Regular expression for local part of an email address. RFC5321 section 4.5.3.1.1 limits
+ * the local part to be at most 64 octets.
+ */
+ private static final String EMAIL_ADDRESS_LOCAL_PART =
+ "[" + EMAIL_CHAR + "]" + "(?:[" + EMAIL_CHAR + "\\.]{1,62}[" + EMAIL_CHAR + "])?";
+
+ /**
+ * Regular expression for the domain part of an email address. RFC5321 section 4.5.3.1.2 limits
+ * the domain to be at most 255 octets.
+ */
+ private static final String EMAIL_ADDRESS_DOMAIN =
+ "(?=.{1,255}(?:\\s|$|^))" + HOST_NAME;
+
+ /**
+ * Regular expression pattern to match email addresses. It excludes double quoted local parts
+ * and the special characters #&~!^`{}/=$*?| that are included in RFC5321.
+ * @hide
+ */
+ public static final Pattern AUTOLINK_EMAIL_ADDRESS = Pattern.compile("(" + WORD_BOUNDARY +
+ "(?:" + EMAIL_ADDRESS_LOCAL_PART + "@" + EMAIL_ADDRESS_DOMAIN + ")" +
+ WORD_BOUNDARY + ")"
+ );
+
public static final Pattern EMAIL_ADDRESS
= Pattern.compile(
"[a-zA-Z0-9\\+\\.\\_\\%\\-\\+]{1,256}" +
diff --git a/core/java/android/view/Surface.aidl b/core/java/android/view/Surface.aidl
deleted file mode 100644
index 90bf37a..0000000
--- a/core/java/android/view/Surface.aidl
+++ /dev/null
@@ -1,20 +0,0 @@
-/* //device/java/android/android/view/Surface.aidl
-**
-** Copyright 2007, 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 android.view;
-
-parcelable Surface;
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index b58c68f..aa86c03 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -36,6 +36,7 @@
throws OutOfResourcesException;
private static native void nativeRelease(long nativeObject);
private static native void nativeDestroy(long nativeObject);
+ private static native void nativeDisconnect(long nativeObject);
private static native Bitmap nativeScreenshot(IBinder displayToken,
Rect sourceCrop, int width, int height, int minLayer, int maxLayer,
@@ -341,6 +342,15 @@
mCloseGuard.close();
}
+ /**
+ * Disconnect any client still connected to the surface.
+ */
+ public void disconnect() {
+ if (mNativeObject != 0) {
+ nativeDisconnect(mNativeObject);
+ }
+ }
+
private void checkNotReleased() {
if (mNativeObject == 0) throw new NullPointerException(
"mNativeObject is null. Have you called release() already?");
diff --git a/core/java/android/view/inputmethod/InputConnectionWrapper.java b/core/java/android/view/inputmethod/InputConnectionWrapper.java
index 65c7654..42d1442 100644
--- a/core/java/android/view/inputmethod/InputConnectionWrapper.java
+++ b/core/java/android/view/inputmethod/InputConnectionWrapper.java
@@ -21,13 +21,22 @@
import android.view.KeyEvent;
/**
- * <p>Wrapper class for proxying calls to another InputConnection. Subclass
- * and have fun!
+ * <p>Wrapper class for proxying calls to another InputConnection. Subclass and have fun!
*/
public class InputConnectionWrapper implements InputConnection {
private InputConnection mTarget;
final boolean mMutable;
-
+
+ /**
+ * Initializes a wrapper.
+ *
+ * <p><b>Caveat:</b> Although the system can accept {@code (InputConnection) null} in some
+ * places, you cannot emulate such a behavior by non-null {@link InputConnectionWrapper} that
+ * has {@code null} in {@code target}.</p>
+ * @param target the {@link InputConnection} to be proxied.
+ * @param mutable set {@code true} to protect this object from being reconfigured to target
+ * another {@link InputConnection}. Note that this is ignored while the target is {@code null}.
+ */
public InputConnectionWrapper(InputConnection target, boolean mutable) {
mMutable = mutable;
mTarget = target;
@@ -35,6 +44,12 @@
/**
* Change the target of the input connection.
+ *
+ * <p><b>Caveat:</b> Although the system can accept {@code (InputConnection) null} in some
+ * places, you cannot emulate such a behavior by non-null {@link InputConnectionWrapper} that
+ * has {@code null} in {@code target}.</p>
+ * @param target the {@link InputConnection} to be proxied.
+ * @throws SecurityException when this wrapper has non-null target and is immutable.
*/
public void setTarget(InputConnection target) {
if (mTarget != null && !mMutable) {
@@ -42,99 +57,195 @@
}
mTarget = target;
}
-
+
+ /**
+ * {@inheritDoc}
+ * @throws NullPointerException if the target is {@code null}.
+ */
public CharSequence getTextBeforeCursor(int n, int flags) {
return mTarget.getTextBeforeCursor(n, flags);
}
-
+
+ /**
+ * {@inheritDoc}
+ * @throws NullPointerException if the target is {@code null}.
+ */
public CharSequence getTextAfterCursor(int n, int flags) {
return mTarget.getTextAfterCursor(n, flags);
}
+ /**
+ * {@inheritDoc}
+ * @throws NullPointerException if the target is {@code null}.
+ */
public CharSequence getSelectedText(int flags) {
return mTarget.getSelectedText(flags);
}
+ /**
+ * {@inheritDoc}
+ * @throws NullPointerException if the target is {@code null}.
+ */
public int getCursorCapsMode(int reqModes) {
return mTarget.getCursorCapsMode(reqModes);
}
-
+
+ /**
+ * {@inheritDoc}
+ * @throws NullPointerException if the target is {@code null}.
+ */
public ExtractedText getExtractedText(ExtractedTextRequest request, int flags) {
return mTarget.getExtractedText(request, flags);
}
+ /**
+ * {@inheritDoc}
+ * @throws NullPointerException if the target is {@code null}.
+ */
public boolean deleteSurroundingTextInCodePoints(int beforeLength, int afterLength) {
return mTarget.deleteSurroundingTextInCodePoints(beforeLength, afterLength);
}
+ /**
+ * {@inheritDoc}
+ * @throws NullPointerException if the target is {@code null}.
+ */
public boolean deleteSurroundingText(int beforeLength, int afterLength) {
return mTarget.deleteSurroundingText(beforeLength, afterLength);
}
+ /**
+ * {@inheritDoc}
+ * @throws NullPointerException if the target is {@code null}.
+ */
public boolean setComposingText(CharSequence text, int newCursorPosition) {
return mTarget.setComposingText(text, newCursorPosition);
}
+ /**
+ * {@inheritDoc}
+ * @throws NullPointerException if the target is {@code null}.
+ */
public boolean setComposingRegion(int start, int end) {
return mTarget.setComposingRegion(start, end);
}
+ /**
+ * {@inheritDoc}
+ * @throws NullPointerException if the target is {@code null}.
+ */
public boolean finishComposingText() {
return mTarget.finishComposingText();
}
-
+
+ /**
+ * {@inheritDoc}
+ * @throws NullPointerException if the target is {@code null}.
+ */
public boolean commitText(CharSequence text, int newCursorPosition) {
return mTarget.commitText(text, newCursorPosition);
}
+ /**
+ * {@inheritDoc}
+ * @throws NullPointerException if the target is {@code null}.
+ */
public boolean commitCompletion(CompletionInfo text) {
return mTarget.commitCompletion(text);
}
+ /**
+ * {@inheritDoc}
+ * @throws NullPointerException if the target is {@code null}.
+ */
public boolean commitCorrection(CorrectionInfo correctionInfo) {
return mTarget.commitCorrection(correctionInfo);
}
+ /**
+ * {@inheritDoc}
+ * @throws NullPointerException if the target is {@code null}.
+ */
public boolean setSelection(int start, int end) {
return mTarget.setSelection(start, end);
}
-
+
+ /**
+ * {@inheritDoc}
+ * @throws NullPointerException if the target is {@code null}.
+ */
public boolean performEditorAction(int editorAction) {
return mTarget.performEditorAction(editorAction);
}
-
+
+ /**
+ * {@inheritDoc}
+ * @throws NullPointerException if the target is {@code null}.
+ */
public boolean performContextMenuAction(int id) {
return mTarget.performContextMenuAction(id);
}
-
+
+ /**
+ * {@inheritDoc}
+ * @throws NullPointerException if the target is {@code null}.
+ */
public boolean beginBatchEdit() {
return mTarget.beginBatchEdit();
}
-
+
+ /**
+ * {@inheritDoc}
+ * @throws NullPointerException if the target is {@code null}.
+ */
public boolean endBatchEdit() {
return mTarget.endBatchEdit();
}
-
+
+ /**
+ * {@inheritDoc}
+ * @throws NullPointerException if the target is {@code null}.
+ */
public boolean sendKeyEvent(KeyEvent event) {
return mTarget.sendKeyEvent(event);
}
+ /**
+ * {@inheritDoc}
+ * @throws NullPointerException if the target is {@code null}.
+ */
public boolean clearMetaKeyStates(int states) {
return mTarget.clearMetaKeyStates(states);
}
-
+
+ /**
+ * {@inheritDoc}
+ * @throws NullPointerException if the target is {@code null}.
+ */
public boolean reportFullscreenMode(boolean enabled) {
return mTarget.reportFullscreenMode(enabled);
}
-
+
+ /**
+ * {@inheritDoc}
+ * @throws NullPointerException if the target is {@code null}.
+ */
public boolean performPrivateCommand(String action, Bundle data) {
return mTarget.performPrivateCommand(action, data);
}
+ /**
+ * {@inheritDoc}
+ * @throws NullPointerException if the target is {@code null}.
+ */
public boolean requestCursorUpdates(int cursorUpdateMode) {
return mTarget.requestCursorUpdates(cursorUpdateMode);
}
+ /**
+ * {@inheritDoc}
+ * @throws NullPointerException if the target is {@code null}.
+ */
public Handler getHandler() {
return mTarget.getHandler();
}
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index 4c015ba..859df43 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -664,7 +664,7 @@
try {
return mService.getInputMethodList();
} catch (RemoteException e) {
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -672,7 +672,7 @@
try {
return mService.getEnabledInputMethodList();
} catch (RemoteException e) {
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -689,7 +689,7 @@
return mService.getEnabledInputMethodSubtypeList(
imi == null ? null : imi.getId(), allowsImplicitlySelectedSubtypes);
} catch (RemoteException e) {
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -697,7 +697,7 @@
try {
mService.updateStatusIcon(imeToken, packageName, iconId);
} catch (RemoteException e) {
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -705,7 +705,7 @@
try {
mService.updateStatusIcon(imeToken, null, 0);
} catch (RemoteException e) {
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -714,7 +714,7 @@
try {
mService.setImeWindowStatus(imeToken, vis, backDisposition);
} catch (RemoteException e) {
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -728,7 +728,7 @@
try {
mService.registerSuggestionSpansForNotification(spans);
} catch (RemoteException e) {
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -737,7 +737,7 @@
try {
mService.notifySuggestionPicked(span, originalString, index);
} catch (RemoteException e) {
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -833,6 +833,7 @@
try {
mService.finishInput(mClient);
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
notifyInputConnectionFinished();
@@ -996,9 +997,8 @@
try {
return mService.showSoftInput(mClient, flags, resultReceiver);
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
-
- return false;
}
}
@@ -1007,6 +1007,7 @@
try {
mService.showSoftInput(mClient, flags, resultReceiver);
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
@@ -1065,8 +1066,8 @@
try {
return mService.hideSoftInput(mClient, flags, resultReceiver);
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
- return false;
}
}
@@ -1421,6 +1422,7 @@
try {
mService.hideSoftInput(mClient, HIDE_NOT_ALWAYS, null);
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
@@ -1476,6 +1478,7 @@
rootView.getWindowToken(), controlFlags, softInputMode, windowFlags, null,
null);
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -1716,7 +1719,7 @@
try {
mService.setInputMethod(token, id);
} catch (RemoteException e) {
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1733,7 +1736,7 @@
try {
mService.setInputMethodAndSubtype(token, id, subtype);
} catch (RemoteException e) {
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1753,7 +1756,7 @@
try {
mService.hideMySoftInput(token, flags);
} catch (RemoteException e) {
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1774,7 +1777,7 @@
try {
mService.showMySoftInput(token, flags);
} catch (RemoteException e) {
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1980,7 +1983,7 @@
SHOW_IM_PICKER_MODE_EXCLUDE_AUXILIARY_SUBTYPES;
mService.showInputMethodPickerFromClient(mClient, mode);
} catch (RemoteException e) {
- Log.w(TAG, "IME died: " + mCurId, e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -1989,7 +1992,7 @@
try {
mService.showInputMethodPickerFromClient(mClient, SHOW_IM_PICKER_MODE_AUTO);
} catch (RemoteException e) {
- Log.w(TAG, "IME died: " + mCurId, e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -2003,7 +2006,7 @@
try {
mService.showInputMethodAndSubtypeEnablerFromClient(mClient, imiId);
} catch (RemoteException e) {
- Log.w(TAG, "IME died: " + mCurId, e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -2018,8 +2021,7 @@
try {
return mService.getCurrentInputMethodSubtype();
} catch (RemoteException e) {
- Log.w(TAG, "IME died: " + mCurId, e);
- return null;
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -2036,8 +2038,7 @@
try {
return mService.setCurrentInputMethodSubtype(subtype);
} catch (RemoteException e) {
- Log.w(TAG, "IME died: " + mCurId, e);
- return false;
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -2071,7 +2072,7 @@
mLastSentUserActionNotificationSequenceNumber =
mNextUserActionNotificationSequenceNumber;
} catch (RemoteException e) {
- Log.w(TAG, "IME died: " + mCurId, e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -2104,7 +2105,7 @@
}
}
} catch (RemoteException e) {
- Log.w(TAG, "IME died: " + mCurId, e);
+ throw e.rethrowFromSystemServer();
}
return ret;
}
@@ -2119,8 +2120,7 @@
try {
return mService.getInputMethodWindowVisibleHeight();
} catch (RemoteException e) {
- Log.w(TAG, "IME died: " + mCurId, e);
- return 0;
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -2139,8 +2139,7 @@
try {
return mService.switchToLastInputMethod(imeToken);
} catch (RemoteException e) {
- Log.w(TAG, "IME died: " + mCurId, e);
- return false;
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -2160,8 +2159,7 @@
try {
return mService.switchToNextInputMethod(imeToken, onlyCurrentIme);
} catch (RemoteException e) {
- Log.w(TAG, "IME died: " + mCurId, e);
- return false;
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -2182,8 +2180,7 @@
try {
return mService.shouldOfferSwitchingToNextInputMethod(imeToken);
} catch (RemoteException e) {
- Log.w(TAG, "IME died: " + mCurId, e);
- return false;
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -2218,7 +2215,7 @@
try {
mService.setAdditionalInputMethodSubtypes(imiId, subtypes);
} catch (RemoteException e) {
- Log.w(TAG, "IME died: " + mCurId, e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -2228,8 +2225,7 @@
try {
return mService.getLastInputMethodSubtype();
} catch (RemoteException e) {
- Log.w(TAG, "IME died: " + mCurId, e);
- return null;
+ throw e.rethrowFromSystemServer();
}
}
}
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index 496f7ee..d2aef0a 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -3078,7 +3078,8 @@
final int motionPosition = mClickMotionPosition;
if (adapter != null && mItemCount > 0 &&
motionPosition != INVALID_POSITION &&
- motionPosition < adapter.getCount() && sameWindow()) {
+ motionPosition < adapter.getCount() && sameWindow() &&
+ adapter.isEnabled(motionPosition)) {
final View view = getChildAt(motionPosition - mFirstPosition);
// If there is no view, something bad happened (the view scrolled off the
// screen, etc.) and we should cancel the click
diff --git a/core/java/android/widget/DatePicker.java b/core/java/android/widget/DatePicker.java
index 87bee44..6e3dbd8 100644
--- a/core/java/android/widget/DatePicker.java
+++ b/core/java/android/widget/DatePicker.java
@@ -23,32 +23,17 @@
import android.content.res.TypedArray;
import android.os.Parcel;
import android.os.Parcelable;
-import android.text.TextUtils;
-import android.text.InputType;
-import android.text.format.DateFormat;
-import android.text.format.DateUtils;
import android.util.AttributeSet;
-import android.util.Log;
import android.util.SparseArray;
-import android.view.LayoutInflater;
import android.view.View;
import android.view.accessibility.AccessibilityEvent;
-import android.view.inputmethod.EditorInfo;
-import android.view.inputmethod.InputMethodManager;
-import android.widget.NumberPicker.OnValueChangeListener;
import com.android.internal.R;
-import java.text.DateFormatSymbols;
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
-import java.util.Arrays;
import java.util.Calendar;
import java.util.Locale;
import java.util.TimeZone;
-import libcore.icu.ICU;
-
/**
* Provides a widget for selecting a date.
* <p>
@@ -527,6 +512,114 @@
protected void onLocaleChanged(Locale locale) {
// Stub.
}
+
+ /**
+ * Class for managing state storing/restoring.
+ */
+ static class SavedState extends View.BaseSavedState {
+ private final int mSelectedYear;
+ private final int mSelectedMonth;
+ private final int mSelectedDay;
+ private final long mMinDate;
+ private final long mMaxDate;
+ private final int mCurrentView;
+ private final int mListPosition;
+ private final int mListPositionOffset;
+
+ public SavedState(Parcelable superState, int year, int month, int day, long minDate,
+ long maxDate) {
+ this(superState, year, month, day, minDate, maxDate, 0, 0, 0);
+ }
+
+ /**
+ * Constructor called from {@link DatePicker#onSaveInstanceState()}
+ */
+ public SavedState(Parcelable superState, int year, int month, int day, long minDate,
+ long maxDate, int currentView, int listPosition, int listPositionOffset) {
+ super(superState);
+ mSelectedYear = year;
+ mSelectedMonth = month;
+ mSelectedDay = day;
+ mMinDate = minDate;
+ mMaxDate = maxDate;
+ mCurrentView = currentView;
+ mListPosition = listPosition;
+ mListPositionOffset = listPositionOffset;
+ }
+
+ /**
+ * Constructor called from {@link #CREATOR}
+ */
+ private SavedState(Parcel in) {
+ super(in);
+ mSelectedYear = in.readInt();
+ mSelectedMonth = in.readInt();
+ mSelectedDay = in.readInt();
+ mMinDate = in.readLong();
+ mMaxDate = in.readLong();
+ mCurrentView = in.readInt();
+ mListPosition = in.readInt();
+ mListPositionOffset = in.readInt();
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ super.writeToParcel(dest, flags);
+ dest.writeInt(mSelectedYear);
+ dest.writeInt(mSelectedMonth);
+ dest.writeInt(mSelectedDay);
+ dest.writeLong(mMinDate);
+ dest.writeLong(mMaxDate);
+ dest.writeInt(mCurrentView);
+ dest.writeInt(mListPosition);
+ dest.writeInt(mListPositionOffset);
+ }
+
+ public int getSelectedDay() {
+ return mSelectedDay;
+ }
+
+ public int getSelectedMonth() {
+ return mSelectedMonth;
+ }
+
+ public int getSelectedYear() {
+ return mSelectedYear;
+ }
+
+ public long getMinDate() {
+ return mMinDate;
+ }
+
+ public long getMaxDate() {
+ return mMaxDate;
+ }
+
+ public int getCurrentView() {
+ return mCurrentView;
+ }
+
+ public int getListPosition() {
+ return mListPosition;
+ }
+
+ public int getListPositionOffset() {
+ return mListPositionOffset;
+ }
+
+ @SuppressWarnings("all")
+ // suppress unused and hiding
+ public static final Parcelable.Creator<SavedState> CREATOR = new Creator<SavedState>() {
+
+ public SavedState createFromParcel(Parcel in) {
+ return new SavedState(in);
+ }
+
+ public SavedState[] newArray(int size) {
+ return new SavedState[size];
+ }
+ };
+ }
}
/**
@@ -535,666 +628,7 @@
*
* @hide
*/
- public static interface ValidationCallback {
+ public interface ValidationCallback {
void onValidationChanged(boolean valid);
}
-
- /**
- * A delegate implementing the basic DatePicker
- */
- private static class DatePickerSpinnerDelegate extends AbstractDatePickerDelegate {
-
- private static final String DATE_FORMAT = "MM/dd/yyyy";
-
- private static final int DEFAULT_START_YEAR = 1900;
-
- private static final int DEFAULT_END_YEAR = 2100;
-
- private static final boolean DEFAULT_CALENDAR_VIEW_SHOWN = true;
-
- private static final boolean DEFAULT_SPINNERS_SHOWN = true;
-
- private static final boolean DEFAULT_ENABLED_STATE = true;
-
- private final LinearLayout mSpinners;
-
- private final NumberPicker mDaySpinner;
-
- private final NumberPicker mMonthSpinner;
-
- private final NumberPicker mYearSpinner;
-
- private final EditText mDaySpinnerInput;
-
- private final EditText mMonthSpinnerInput;
-
- private final EditText mYearSpinnerInput;
-
- private final CalendarView mCalendarView;
-
- private String[] mShortMonths;
-
- private final java.text.DateFormat mDateFormat = new SimpleDateFormat(DATE_FORMAT);
-
- private int mNumberOfMonths;
-
- private Calendar mTempDate;
-
- private Calendar mMinDate;
-
- private Calendar mMaxDate;
-
- private Calendar mCurrentDate;
-
- private boolean mIsEnabled = DEFAULT_ENABLED_STATE;
-
- DatePickerSpinnerDelegate(DatePicker delegator, Context context, AttributeSet attrs,
- int defStyleAttr, int defStyleRes) {
- super(delegator, context);
-
- mDelegator = delegator;
- mContext = context;
-
- // initialization based on locale
- setCurrentLocale(Locale.getDefault());
-
- final TypedArray attributesArray = context.obtainStyledAttributes(attrs,
- R.styleable.DatePicker, defStyleAttr, defStyleRes);
- boolean spinnersShown = attributesArray.getBoolean(R.styleable.DatePicker_spinnersShown,
- DEFAULT_SPINNERS_SHOWN);
- boolean calendarViewShown = attributesArray.getBoolean(
- R.styleable.DatePicker_calendarViewShown, DEFAULT_CALENDAR_VIEW_SHOWN);
- int startYear = attributesArray.getInt(R.styleable.DatePicker_startYear,
- DEFAULT_START_YEAR);
- int endYear = attributesArray.getInt(R.styleable.DatePicker_endYear, DEFAULT_END_YEAR);
- String minDate = attributesArray.getString(R.styleable.DatePicker_minDate);
- String maxDate = attributesArray.getString(R.styleable.DatePicker_maxDate);
- int layoutResourceId = attributesArray.getResourceId(
- R.styleable.DatePicker_legacyLayout, R.layout.date_picker_legacy);
- attributesArray.recycle();
-
- LayoutInflater inflater = (LayoutInflater) context
- .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- inflater.inflate(layoutResourceId, mDelegator, true);
-
- OnValueChangeListener onChangeListener = new OnValueChangeListener() {
- public void onValueChange(NumberPicker picker, int oldVal, int newVal) {
- updateInputState();
- mTempDate.setTimeInMillis(mCurrentDate.getTimeInMillis());
- // take care of wrapping of days and months to update greater fields
- if (picker == mDaySpinner) {
- int maxDayOfMonth = mTempDate.getActualMaximum(Calendar.DAY_OF_MONTH);
- if (oldVal == maxDayOfMonth && newVal == 1) {
- mTempDate.add(Calendar.DAY_OF_MONTH, 1);
- } else if (oldVal == 1 && newVal == maxDayOfMonth) {
- mTempDate.add(Calendar.DAY_OF_MONTH, -1);
- } else {
- mTempDate.add(Calendar.DAY_OF_MONTH, newVal - oldVal);
- }
- } else if (picker == mMonthSpinner) {
- if (oldVal == 11 && newVal == 0) {
- mTempDate.add(Calendar.MONTH, 1);
- } else if (oldVal == 0 && newVal == 11) {
- mTempDate.add(Calendar.MONTH, -1);
- } else {
- mTempDate.add(Calendar.MONTH, newVal - oldVal);
- }
- } else if (picker == mYearSpinner) {
- mTempDate.set(Calendar.YEAR, newVal);
- } else {
- throw new IllegalArgumentException();
- }
- // now set the date to the adjusted one
- setDate(mTempDate.get(Calendar.YEAR), mTempDate.get(Calendar.MONTH),
- mTempDate.get(Calendar.DAY_OF_MONTH));
- updateSpinners();
- updateCalendarView();
- notifyDateChanged();
- }
- };
-
- mSpinners = (LinearLayout) mDelegator.findViewById(R.id.pickers);
-
- // calendar view day-picker
- mCalendarView = (CalendarView) mDelegator.findViewById(R.id.calendar_view);
- mCalendarView.setOnDateChangeListener(new CalendarView.OnDateChangeListener() {
- public void onSelectedDayChange(CalendarView view, int year, int month, int monthDay) {
- setDate(year, month, monthDay);
- updateSpinners();
- notifyDateChanged();
- }
- });
-
- // day
- mDaySpinner = (NumberPicker) mDelegator.findViewById(R.id.day);
- mDaySpinner.setFormatter(NumberPicker.getTwoDigitFormatter());
- mDaySpinner.setOnLongPressUpdateInterval(100);
- mDaySpinner.setOnValueChangedListener(onChangeListener);
- mDaySpinnerInput = (EditText) mDaySpinner.findViewById(R.id.numberpicker_input);
-
- // month
- mMonthSpinner = (NumberPicker) mDelegator.findViewById(R.id.month);
- mMonthSpinner.setMinValue(0);
- mMonthSpinner.setMaxValue(mNumberOfMonths - 1);
- mMonthSpinner.setDisplayedValues(mShortMonths);
- mMonthSpinner.setOnLongPressUpdateInterval(200);
- mMonthSpinner.setOnValueChangedListener(onChangeListener);
- mMonthSpinnerInput = (EditText) mMonthSpinner.findViewById(R.id.numberpicker_input);
-
- // year
- mYearSpinner = (NumberPicker) mDelegator.findViewById(R.id.year);
- mYearSpinner.setOnLongPressUpdateInterval(100);
- mYearSpinner.setOnValueChangedListener(onChangeListener);
- mYearSpinnerInput = (EditText) mYearSpinner.findViewById(R.id.numberpicker_input);
-
- // show only what the user required but make sure we
- // show something and the spinners have higher priority
- if (!spinnersShown && !calendarViewShown) {
- setSpinnersShown(true);
- } else {
- setSpinnersShown(spinnersShown);
- setCalendarViewShown(calendarViewShown);
- }
-
- // set the min date giving priority of the minDate over startYear
- mTempDate.clear();
- if (!TextUtils.isEmpty(minDate)) {
- if (!parseDate(minDate, mTempDate)) {
- mTempDate.set(startYear, 0, 1);
- }
- } else {
- mTempDate.set(startYear, 0, 1);
- }
- setMinDate(mTempDate.getTimeInMillis());
-
- // set the max date giving priority of the maxDate over endYear
- mTempDate.clear();
- if (!TextUtils.isEmpty(maxDate)) {
- if (!parseDate(maxDate, mTempDate)) {
- mTempDate.set(endYear, 11, 31);
- }
- } else {
- mTempDate.set(endYear, 11, 31);
- }
- setMaxDate(mTempDate.getTimeInMillis());
-
- // initialize to current date
- mCurrentDate.setTimeInMillis(System.currentTimeMillis());
- init(mCurrentDate.get(Calendar.YEAR), mCurrentDate.get(Calendar.MONTH), mCurrentDate
- .get(Calendar.DAY_OF_MONTH), null);
-
- // re-order the number spinners to match the current date format
- reorderSpinners();
-
- // accessibility
- setContentDescriptions();
-
- // If not explicitly specified this view is important for accessibility.
- if (mDelegator.getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
- mDelegator.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
- }
- }
-
- @Override
- public void init(int year, int monthOfYear, int dayOfMonth,
- OnDateChangedListener onDateChangedListener) {
- setDate(year, monthOfYear, dayOfMonth);
- updateSpinners();
- updateCalendarView();
- mOnDateChangedListener = onDateChangedListener;
- }
-
- @Override
- public void updateDate(int year, int month, int dayOfMonth) {
- if (!isNewDate(year, month, dayOfMonth)) {
- return;
- }
- setDate(year, month, dayOfMonth);
- updateSpinners();
- updateCalendarView();
- notifyDateChanged();
- }
-
- @Override
- public int getYear() {
- return mCurrentDate.get(Calendar.YEAR);
- }
-
- @Override
- public int getMonth() {
- return mCurrentDate.get(Calendar.MONTH);
- }
-
- @Override
- public int getDayOfMonth() {
- return mCurrentDate.get(Calendar.DAY_OF_MONTH);
- }
-
- @Override
- public void setFirstDayOfWeek(int firstDayOfWeek) {
- mCalendarView.setFirstDayOfWeek(firstDayOfWeek);
- }
-
- @Override
- public int getFirstDayOfWeek() {
- return mCalendarView.getFirstDayOfWeek();
- }
-
- @Override
- public void setMinDate(long minDate) {
- mTempDate.setTimeInMillis(minDate);
- if (mTempDate.get(Calendar.YEAR) == mMinDate.get(Calendar.YEAR)
- && mTempDate.get(Calendar.DAY_OF_YEAR) != mMinDate.get(Calendar.DAY_OF_YEAR)) {
- return;
- }
- mMinDate.setTimeInMillis(minDate);
- mCalendarView.setMinDate(minDate);
- if (mCurrentDate.before(mMinDate)) {
- mCurrentDate.setTimeInMillis(mMinDate.getTimeInMillis());
- updateCalendarView();
- }
- updateSpinners();
- }
-
- @Override
- public Calendar getMinDate() {
- final Calendar minDate = Calendar.getInstance();
- minDate.setTimeInMillis(mCalendarView.getMinDate());
- return minDate;
- }
-
- @Override
- public void setMaxDate(long maxDate) {
- mTempDate.setTimeInMillis(maxDate);
- if (mTempDate.get(Calendar.YEAR) == mMaxDate.get(Calendar.YEAR)
- && mTempDate.get(Calendar.DAY_OF_YEAR) != mMaxDate.get(Calendar.DAY_OF_YEAR)) {
- return;
- }
- mMaxDate.setTimeInMillis(maxDate);
- mCalendarView.setMaxDate(maxDate);
- if (mCurrentDate.after(mMaxDate)) {
- mCurrentDate.setTimeInMillis(mMaxDate.getTimeInMillis());
- updateCalendarView();
- }
- updateSpinners();
- }
-
- @Override
- public Calendar getMaxDate() {
- final Calendar maxDate = Calendar.getInstance();
- maxDate.setTimeInMillis(mCalendarView.getMaxDate());
- return maxDate;
- }
-
- @Override
- public void setEnabled(boolean enabled) {
- mDaySpinner.setEnabled(enabled);
- mMonthSpinner.setEnabled(enabled);
- mYearSpinner.setEnabled(enabled);
- mCalendarView.setEnabled(enabled);
- mIsEnabled = enabled;
- }
-
- @Override
- public boolean isEnabled() {
- return mIsEnabled;
- }
-
- @Override
- public CalendarView getCalendarView() {
- return mCalendarView;
- }
-
- @Override
- public void setCalendarViewShown(boolean shown) {
- mCalendarView.setVisibility(shown ? VISIBLE : GONE);
- }
-
- @Override
- public boolean getCalendarViewShown() {
- return (mCalendarView.getVisibility() == View.VISIBLE);
- }
-
- @Override
- public void setSpinnersShown(boolean shown) {
- mSpinners.setVisibility(shown ? VISIBLE : GONE);
- }
-
- @Override
- public boolean getSpinnersShown() {
- return mSpinners.isShown();
- }
-
- @Override
- public void onConfigurationChanged(Configuration newConfig) {
- setCurrentLocale(newConfig.locale);
- }
-
- @Override
- public Parcelable onSaveInstanceState(Parcelable superState) {
- return new SavedState(superState, getYear(), getMonth(), getDayOfMonth());
- }
-
- @Override
- public void onRestoreInstanceState(Parcelable state) {
- SavedState ss = (SavedState) state;
- setDate(ss.mYear, ss.mMonth, ss.mDay);
- updateSpinners();
- updateCalendarView();
- }
-
- @Override
- public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
- onPopulateAccessibilityEvent(event);
- return true;
- }
-
- @Override
- public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
- final int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_YEAR;
- String selectedDateUtterance = DateUtils.formatDateTime(mContext,
- mCurrentDate.getTimeInMillis(), flags);
- event.getText().add(selectedDateUtterance);
- }
-
- /**
- * Sets the current locale.
- *
- * @param locale The current locale.
- */
- @Override
- protected void setCurrentLocale(Locale locale) {
- super.setCurrentLocale(locale);
-
- mTempDate = getCalendarForLocale(mTempDate, locale);
- mMinDate = getCalendarForLocale(mMinDate, locale);
- mMaxDate = getCalendarForLocale(mMaxDate, locale);
- mCurrentDate = getCalendarForLocale(mCurrentDate, locale);
-
- mNumberOfMonths = mTempDate.getActualMaximum(Calendar.MONTH) + 1;
- mShortMonths = new DateFormatSymbols().getShortMonths();
-
- if (usingNumericMonths()) {
- // We're in a locale where a date should either be all-numeric, or all-text.
- // All-text would require custom NumberPicker formatters for day and year.
- mShortMonths = new String[mNumberOfMonths];
- for (int i = 0; i < mNumberOfMonths; ++i) {
- mShortMonths[i] = String.format("%d", i + 1);
- }
- }
- }
-
- /**
- * Tests whether the current locale is one where there are no real month names,
- * such as Chinese, Japanese, or Korean locales.
- */
- private boolean usingNumericMonths() {
- return Character.isDigit(mShortMonths[Calendar.JANUARY].charAt(0));
- }
-
- /**
- * Gets a calendar for locale bootstrapped with the value of a given calendar.
- *
- * @param oldCalendar The old calendar.
- * @param locale The locale.
- */
- private Calendar getCalendarForLocale(Calendar oldCalendar, Locale locale) {
- if (oldCalendar == null) {
- return Calendar.getInstance(locale);
- } else {
- final long currentTimeMillis = oldCalendar.getTimeInMillis();
- Calendar newCalendar = Calendar.getInstance(locale);
- newCalendar.setTimeInMillis(currentTimeMillis);
- return newCalendar;
- }
- }
-
- /**
- * Reorders the spinners according to the date format that is
- * explicitly set by the user and if no such is set fall back
- * to the current locale's default format.
- */
- private void reorderSpinners() {
- mSpinners.removeAllViews();
- // We use numeric spinners for year and day, but textual months. Ask icu4c what
- // order the user's locale uses for that combination. http://b/7207103.
- String pattern = DateFormat.getBestDateTimePattern(Locale.getDefault(), "yyyyMMMdd");
- char[] order = ICU.getDateFormatOrder(pattern);
- final int spinnerCount = order.length;
- for (int i = 0; i < spinnerCount; i++) {
- switch (order[i]) {
- case 'd':
- mSpinners.addView(mDaySpinner);
- setImeOptions(mDaySpinner, spinnerCount, i);
- break;
- case 'M':
- mSpinners.addView(mMonthSpinner);
- setImeOptions(mMonthSpinner, spinnerCount, i);
- break;
- case 'y':
- mSpinners.addView(mYearSpinner);
- setImeOptions(mYearSpinner, spinnerCount, i);
- break;
- default:
- throw new IllegalArgumentException(Arrays.toString(order));
- }
- }
- }
-
- /**
- * Parses the given <code>date</code> and in case of success sets the result
- * to the <code>outDate</code>.
- *
- * @return True if the date was parsed.
- */
- private boolean parseDate(String date, Calendar outDate) {
- try {
- outDate.setTime(mDateFormat.parse(date));
- return true;
- } catch (ParseException e) {
- Log.w(LOG_TAG, "Date: " + date + " not in format: " + DATE_FORMAT);
- return false;
- }
- }
-
- private boolean isNewDate(int year, int month, int dayOfMonth) {
- return (mCurrentDate.get(Calendar.YEAR) != year
- || mCurrentDate.get(Calendar.MONTH) != month
- || mCurrentDate.get(Calendar.DAY_OF_MONTH) != dayOfMonth);
- }
-
- private void setDate(int year, int month, int dayOfMonth) {
- mCurrentDate.set(year, month, dayOfMonth);
- if (mCurrentDate.before(mMinDate)) {
- mCurrentDate.setTimeInMillis(mMinDate.getTimeInMillis());
- } else if (mCurrentDate.after(mMaxDate)) {
- mCurrentDate.setTimeInMillis(mMaxDate.getTimeInMillis());
- }
- }
-
- private void updateSpinners() {
- // set the spinner ranges respecting the min and max dates
- if (mCurrentDate.equals(mMinDate)) {
- mDaySpinner.setMinValue(mCurrentDate.get(Calendar.DAY_OF_MONTH));
- mDaySpinner.setMaxValue(mCurrentDate.getActualMaximum(Calendar.DAY_OF_MONTH));
- mDaySpinner.setWrapSelectorWheel(false);
- mMonthSpinner.setDisplayedValues(null);
- mMonthSpinner.setMinValue(mCurrentDate.get(Calendar.MONTH));
- mMonthSpinner.setMaxValue(mCurrentDate.getActualMaximum(Calendar.MONTH));
- mMonthSpinner.setWrapSelectorWheel(false);
- } else if (mCurrentDate.equals(mMaxDate)) {
- mDaySpinner.setMinValue(mCurrentDate.getActualMinimum(Calendar.DAY_OF_MONTH));
- mDaySpinner.setMaxValue(mCurrentDate.get(Calendar.DAY_OF_MONTH));
- mDaySpinner.setWrapSelectorWheel(false);
- mMonthSpinner.setDisplayedValues(null);
- mMonthSpinner.setMinValue(mCurrentDate.getActualMinimum(Calendar.MONTH));
- mMonthSpinner.setMaxValue(mCurrentDate.get(Calendar.MONTH));
- mMonthSpinner.setWrapSelectorWheel(false);
- } else {
- mDaySpinner.setMinValue(1);
- mDaySpinner.setMaxValue(mCurrentDate.getActualMaximum(Calendar.DAY_OF_MONTH));
- mDaySpinner.setWrapSelectorWheel(true);
- mMonthSpinner.setDisplayedValues(null);
- mMonthSpinner.setMinValue(0);
- mMonthSpinner.setMaxValue(11);
- mMonthSpinner.setWrapSelectorWheel(true);
- }
-
- // make sure the month names are a zero based array
- // with the months in the month spinner
- String[] displayedValues = Arrays.copyOfRange(mShortMonths,
- mMonthSpinner.getMinValue(), mMonthSpinner.getMaxValue() + 1);
- mMonthSpinner.setDisplayedValues(displayedValues);
-
- // year spinner range does not change based on the current date
- mYearSpinner.setMinValue(mMinDate.get(Calendar.YEAR));
- mYearSpinner.setMaxValue(mMaxDate.get(Calendar.YEAR));
- mYearSpinner.setWrapSelectorWheel(false);
-
- // set the spinner values
- mYearSpinner.setValue(mCurrentDate.get(Calendar.YEAR));
- mMonthSpinner.setValue(mCurrentDate.get(Calendar.MONTH));
- mDaySpinner.setValue(mCurrentDate.get(Calendar.DAY_OF_MONTH));
-
- if (usingNumericMonths()) {
- mMonthSpinnerInput.setRawInputType(InputType.TYPE_CLASS_NUMBER);
- }
- }
-
- /**
- * Updates the calendar view with the current date.
- */
- private void updateCalendarView() {
- mCalendarView.setDate(mCurrentDate.getTimeInMillis(), false, false);
- }
-
-
- /**
- * Notifies the listener, if such, for a change in the selected date.
- */
- private void notifyDateChanged() {
- mDelegator.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);
- if (mOnDateChangedListener != null) {
- mOnDateChangedListener.onDateChanged(mDelegator, getYear(), getMonth(),
- getDayOfMonth());
- }
- }
-
- /**
- * Sets the IME options for a spinner based on its ordering.
- *
- * @param spinner The spinner.
- * @param spinnerCount The total spinner count.
- * @param spinnerIndex The index of the given spinner.
- */
- private void setImeOptions(NumberPicker spinner, int spinnerCount, int spinnerIndex) {
- final int imeOptions;
- if (spinnerIndex < spinnerCount - 1) {
- imeOptions = EditorInfo.IME_ACTION_NEXT;
- } else {
- imeOptions = EditorInfo.IME_ACTION_DONE;
- }
- TextView input = (TextView) spinner.findViewById(R.id.numberpicker_input);
- input.setImeOptions(imeOptions);
- }
-
- private void setContentDescriptions() {
- // Day
- trySetContentDescription(mDaySpinner, R.id.increment,
- R.string.date_picker_increment_day_button);
- trySetContentDescription(mDaySpinner, R.id.decrement,
- R.string.date_picker_decrement_day_button);
- // Month
- trySetContentDescription(mMonthSpinner, R.id.increment,
- R.string.date_picker_increment_month_button);
- trySetContentDescription(mMonthSpinner, R.id.decrement,
- R.string.date_picker_decrement_month_button);
- // Year
- trySetContentDescription(mYearSpinner, R.id.increment,
- R.string.date_picker_increment_year_button);
- trySetContentDescription(mYearSpinner, R.id.decrement,
- R.string.date_picker_decrement_year_button);
- }
-
- private void trySetContentDescription(View root, int viewId, int contDescResId) {
- View target = root.findViewById(viewId);
- if (target != null) {
- target.setContentDescription(mContext.getString(contDescResId));
- }
- }
-
- private void updateInputState() {
- // Make sure that if the user changes the value and the IME is active
- // for one of the inputs if this widget, the IME is closed. If the user
- // changed the value via the IME and there is a next input the IME will
- // be shown, otherwise the user chose another means of changing the
- // value and having the IME up makes no sense.
- InputMethodManager inputMethodManager = InputMethodManager.peekInstance();
- if (inputMethodManager != null) {
- if (inputMethodManager.isActive(mYearSpinnerInput)) {
- mYearSpinnerInput.clearFocus();
- inputMethodManager.hideSoftInputFromWindow(mDelegator.getWindowToken(), 0);
- } else if (inputMethodManager.isActive(mMonthSpinnerInput)) {
- mMonthSpinnerInput.clearFocus();
- inputMethodManager.hideSoftInputFromWindow(mDelegator.getWindowToken(), 0);
- } else if (inputMethodManager.isActive(mDaySpinnerInput)) {
- mDaySpinnerInput.clearFocus();
- inputMethodManager.hideSoftInputFromWindow(mDelegator.getWindowToken(), 0);
- }
- }
- }
- }
-
- /**
- * Class for managing state storing/restoring.
- */
- private static class SavedState extends BaseSavedState {
-
- private final int mYear;
-
- private final int mMonth;
-
- private final int mDay;
-
- /**
- * Constructor called from {@link DatePicker#onSaveInstanceState()}
- */
- private SavedState(Parcelable superState, int year, int month, int day) {
- super(superState);
- mYear = year;
- mMonth = month;
- mDay = day;
- }
-
- /**
- * Constructor called from {@link #CREATOR}
- */
- private SavedState(Parcel in) {
- super(in);
- mYear = in.readInt();
- mMonth = in.readInt();
- mDay = in.readInt();
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- super.writeToParcel(dest, flags);
- dest.writeInt(mYear);
- dest.writeInt(mMonth);
- dest.writeInt(mDay);
- }
-
- @SuppressWarnings("all")
- // suppress unused and hiding
- public static final Parcelable.Creator<SavedState> CREATOR = new Creator<SavedState>() {
-
- public SavedState createFromParcel(Parcel in) {
- return new SavedState(in);
- }
-
- public SavedState[] newArray(int size) {
- return new SavedState[size];
- }
- };
- }
}
diff --git a/core/java/android/widget/DatePickerCalendarDelegate.java b/core/java/android/widget/DatePickerCalendarDelegate.java
index cbb6109..5adac01 100755
--- a/core/java/android/widget/DatePickerCalendarDelegate.java
+++ b/core/java/android/widget/DatePickerCalendarDelegate.java
@@ -16,13 +16,14 @@
package android.widget;
+import com.android.internal.R;
+
import android.annotation.Nullable;
import android.content.Context;
import android.content.res.ColorStateList;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.content.res.TypedArray;
-import android.os.Parcel;
import android.os.Parcelable;
import android.text.format.DateFormat;
import android.text.format.DateUtils;
@@ -37,8 +38,6 @@
import android.widget.DayPickerView.OnDaySelectedListener;
import android.widget.YearPickerView.OnYearSelectedListener;
-import com.android.internal.R;
-
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Locale;
@@ -550,25 +549,27 @@
@Override
public void onRestoreInstanceState(Parcelable state) {
- final SavedState ss = (SavedState) state;
+ if (state instanceof SavedState) {
+ final SavedState ss = (SavedState) state;
- // TODO: Move instance state into DayPickerView, YearPickerView.
- mCurrentDate.set(ss.getSelectedYear(), ss.getSelectedMonth(), ss.getSelectedDay());
- mMinDate.setTimeInMillis(ss.getMinDate());
- mMaxDate.setTimeInMillis(ss.getMaxDate());
+ // TODO: Move instance state into DayPickerView, YearPickerView.
+ mCurrentDate.set(ss.getSelectedYear(), ss.getSelectedMonth(), ss.getSelectedDay());
+ mMinDate.setTimeInMillis(ss.getMinDate());
+ mMaxDate.setTimeInMillis(ss.getMaxDate());
- onCurrentDateChanged(false);
+ onCurrentDateChanged(false);
- final int currentView = ss.getCurrentView();
- setCurrentView(currentView);
+ final int currentView = ss.getCurrentView();
+ setCurrentView(currentView);
- final int listPosition = ss.getListPosition();
- if (listPosition != -1) {
- if (currentView == VIEW_MONTH_DAY) {
- mDayPickerView.setPosition(listPosition);
- } else if (currentView == VIEW_YEAR) {
- final int listPositionOffset = ss.getListPositionOffset();
- mYearPickerView.setSelectionFromTop(listPosition, listPositionOffset);
+ final int listPosition = ss.getListPosition();
+ if (listPosition != -1) {
+ if (currentView == VIEW_MONTH_DAY) {
+ mDayPickerView.setPosition(listPosition);
+ } else if (currentView == VIEW_YEAR) {
+ final int listPositionOffset = ss.getListPositionOffset();
+ mYearPickerView.setSelectionFromTop(listPosition, listPositionOffset);
+ }
}
}
}
@@ -613,108 +614,4 @@
private void tryVibrate() {
mDelegator.performHapticFeedback(HapticFeedbackConstants.CALENDAR_DATE);
}
-
- /**
- * Class for managing state storing/restoring.
- */
- private static class SavedState extends View.BaseSavedState {
- private final int mSelectedYear;
- private final int mSelectedMonth;
- private final int mSelectedDay;
- private final long mMinDate;
- private final long mMaxDate;
- private final int mCurrentView;
- private final int mListPosition;
- private final int mListPositionOffset;
-
- /**
- * Constructor called from {@link DatePicker#onSaveInstanceState()}
- */
- private SavedState(Parcelable superState, int year, int month, int day,
- long minDate, long maxDate, int currentView, int listPosition,
- int listPositionOffset) {
- super(superState);
- mSelectedYear = year;
- mSelectedMonth = month;
- mSelectedDay = day;
- mMinDate = minDate;
- mMaxDate = maxDate;
- mCurrentView = currentView;
- mListPosition = listPosition;
- mListPositionOffset = listPositionOffset;
- }
-
- /**
- * Constructor called from {@link #CREATOR}
- */
- private SavedState(Parcel in) {
- super(in);
- mSelectedYear = in.readInt();
- mSelectedMonth = in.readInt();
- mSelectedDay = in.readInt();
- mMinDate = in.readLong();
- mMaxDate = in.readLong();
- mCurrentView = in.readInt();
- mListPosition = in.readInt();
- mListPositionOffset = in.readInt();
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- super.writeToParcel(dest, flags);
- dest.writeInt(mSelectedYear);
- dest.writeInt(mSelectedMonth);
- dest.writeInt(mSelectedDay);
- dest.writeLong(mMinDate);
- dest.writeLong(mMaxDate);
- dest.writeInt(mCurrentView);
- dest.writeInt(mListPosition);
- dest.writeInt(mListPositionOffset);
- }
-
- public int getSelectedDay() {
- return mSelectedDay;
- }
-
- public int getSelectedMonth() {
- return mSelectedMonth;
- }
-
- public int getSelectedYear() {
- return mSelectedYear;
- }
-
- public long getMinDate() {
- return mMinDate;
- }
-
- public long getMaxDate() {
- return mMaxDate;
- }
-
- public int getCurrentView() {
- return mCurrentView;
- }
-
- public int getListPosition() {
- return mListPosition;
- }
-
- public int getListPositionOffset() {
- return mListPositionOffset;
- }
-
- @SuppressWarnings("all")
- // suppress unused and hiding
- public static final Parcelable.Creator<SavedState> CREATOR = new Creator<SavedState>() {
-
- public SavedState createFromParcel(Parcel in) {
- return new SavedState(in);
- }
-
- public SavedState[] newArray(int size) {
- return new SavedState[size];
- }
- };
- }
}
diff --git a/core/java/android/widget/DatePickerSpinnerDelegate.java b/core/java/android/widget/DatePickerSpinnerDelegate.java
new file mode 100644
index 0000000..255de79
--- /dev/null
+++ b/core/java/android/widget/DatePickerSpinnerDelegate.java
@@ -0,0 +1,652 @@
+/*
+ * 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.
+ */
+
+package android.widget;
+
+import android.content.Context;
+import android.content.res.Configuration;
+import android.content.res.TypedArray;
+import android.os.Parcelable;
+import android.text.InputType;
+import android.text.TextUtils;
+import android.text.format.DateFormat;
+import android.text.format.DateUtils;
+import android.util.AttributeSet;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.inputmethod.EditorInfo;
+import android.view.inputmethod.InputMethodManager;
+import android.widget.DatePicker.AbstractDatePickerDelegate;
+import android.widget.NumberPicker.OnValueChangeListener;
+
+import java.text.DateFormatSymbols;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Arrays;
+import java.util.Calendar;
+import java.util.Locale;
+
+import libcore.icu.ICU;
+
+/**
+ * A delegate implementing the basic DatePicker
+ */
+class DatePickerSpinnerDelegate extends AbstractDatePickerDelegate {
+
+ private static final String DATE_FORMAT = "MM/dd/yyyy";
+
+ private static final int DEFAULT_START_YEAR = 1900;
+
+ private static final int DEFAULT_END_YEAR = 2100;
+
+ private static final boolean DEFAULT_CALENDAR_VIEW_SHOWN = true;
+
+ private static final boolean DEFAULT_SPINNERS_SHOWN = true;
+
+ private static final boolean DEFAULT_ENABLED_STATE = true;
+
+ private final LinearLayout mSpinners;
+
+ private final NumberPicker mDaySpinner;
+
+ private final NumberPicker mMonthSpinner;
+
+ private final NumberPicker mYearSpinner;
+
+ private final EditText mDaySpinnerInput;
+
+ private final EditText mMonthSpinnerInput;
+
+ private final EditText mYearSpinnerInput;
+
+ private final CalendarView mCalendarView;
+
+ private String[] mShortMonths;
+
+ private final java.text.DateFormat mDateFormat = new SimpleDateFormat(DATE_FORMAT);
+
+ private int mNumberOfMonths;
+
+ private Calendar mTempDate;
+
+ private Calendar mMinDate;
+
+ private Calendar mMaxDate;
+
+ private Calendar mCurrentDate;
+
+ private boolean mIsEnabled = DEFAULT_ENABLED_STATE;
+
+ DatePickerSpinnerDelegate(DatePicker delegator, Context context, AttributeSet attrs,
+ int defStyleAttr, int defStyleRes) {
+ super(delegator, context);
+
+ mDelegator = delegator;
+ mContext = context;
+
+ // initialization based on locale
+ setCurrentLocale(Locale.getDefault());
+
+ final TypedArray attributesArray = context.obtainStyledAttributes(attrs,
+ com.android.internal.R.styleable.DatePicker, defStyleAttr, defStyleRes);
+ boolean spinnersShown = attributesArray.getBoolean(com.android.internal.R.styleable.DatePicker_spinnersShown,
+ DEFAULT_SPINNERS_SHOWN);
+ boolean calendarViewShown = attributesArray.getBoolean(
+ com.android.internal.R.styleable.DatePicker_calendarViewShown, DEFAULT_CALENDAR_VIEW_SHOWN);
+ int startYear = attributesArray.getInt(com.android.internal.R.styleable.DatePicker_startYear,
+ DEFAULT_START_YEAR);
+ int endYear = attributesArray.getInt(com.android.internal.R.styleable.DatePicker_endYear, DEFAULT_END_YEAR);
+ String minDate = attributesArray.getString(com.android.internal.R.styleable.DatePicker_minDate);
+ String maxDate = attributesArray.getString(com.android.internal.R.styleable.DatePicker_maxDate);
+ int layoutResourceId = attributesArray.getResourceId(
+ com.android.internal.R.styleable.DatePicker_legacyLayout, com.android.internal.R.layout.date_picker_legacy);
+ attributesArray.recycle();
+
+ LayoutInflater inflater = (LayoutInflater) context
+ .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+ inflater.inflate(layoutResourceId, mDelegator, true);
+
+ OnValueChangeListener onChangeListener = new OnValueChangeListener() {
+ public void onValueChange(NumberPicker picker, int oldVal, int newVal) {
+ updateInputState();
+ mTempDate.setTimeInMillis(mCurrentDate.getTimeInMillis());
+ // take care of wrapping of days and months to update greater fields
+ if (picker == mDaySpinner) {
+ int maxDayOfMonth = mTempDate.getActualMaximum(Calendar.DAY_OF_MONTH);
+ if (oldVal == maxDayOfMonth && newVal == 1) {
+ mTempDate.add(Calendar.DAY_OF_MONTH, 1);
+ } else if (oldVal == 1 && newVal == maxDayOfMonth) {
+ mTempDate.add(Calendar.DAY_OF_MONTH, -1);
+ } else {
+ mTempDate.add(Calendar.DAY_OF_MONTH, newVal - oldVal);
+ }
+ } else if (picker == mMonthSpinner) {
+ if (oldVal == 11 && newVal == 0) {
+ mTempDate.add(Calendar.MONTH, 1);
+ } else if (oldVal == 0 && newVal == 11) {
+ mTempDate.add(Calendar.MONTH, -1);
+ } else {
+ mTempDate.add(Calendar.MONTH, newVal - oldVal);
+ }
+ } else if (picker == mYearSpinner) {
+ mTempDate.set(Calendar.YEAR, newVal);
+ } else {
+ throw new IllegalArgumentException();
+ }
+ // now set the date to the adjusted one
+ setDate(mTempDate.get(Calendar.YEAR), mTempDate.get(Calendar.MONTH),
+ mTempDate.get(Calendar.DAY_OF_MONTH));
+ updateSpinners();
+ updateCalendarView();
+ notifyDateChanged();
+ }
+ };
+
+ mSpinners = (LinearLayout) mDelegator.findViewById(com.android.internal.R.id.pickers);
+
+ // calendar view day-picker
+ mCalendarView = (CalendarView) mDelegator.findViewById(com.android.internal.R.id.calendar_view);
+ mCalendarView.setOnDateChangeListener(new CalendarView.OnDateChangeListener() {
+ public void onSelectedDayChange(CalendarView view, int year, int month, int monthDay) {
+ setDate(year, month, monthDay);
+ updateSpinners();
+ notifyDateChanged();
+ }
+ });
+
+ // day
+ mDaySpinner = (NumberPicker) mDelegator.findViewById(com.android.internal.R.id.day);
+ mDaySpinner.setFormatter(NumberPicker.getTwoDigitFormatter());
+ mDaySpinner.setOnLongPressUpdateInterval(100);
+ mDaySpinner.setOnValueChangedListener(onChangeListener);
+ mDaySpinnerInput = (EditText) mDaySpinner.findViewById(com.android.internal.R.id.numberpicker_input);
+
+ // month
+ mMonthSpinner = (NumberPicker) mDelegator.findViewById(com.android.internal.R.id.month);
+ mMonthSpinner.setMinValue(0);
+ mMonthSpinner.setMaxValue(mNumberOfMonths - 1);
+ mMonthSpinner.setDisplayedValues(mShortMonths);
+ mMonthSpinner.setOnLongPressUpdateInterval(200);
+ mMonthSpinner.setOnValueChangedListener(onChangeListener);
+ mMonthSpinnerInput = (EditText) mMonthSpinner.findViewById(com.android.internal.R.id.numberpicker_input);
+
+ // year
+ mYearSpinner = (NumberPicker) mDelegator.findViewById(com.android.internal.R.id.year);
+ mYearSpinner.setOnLongPressUpdateInterval(100);
+ mYearSpinner.setOnValueChangedListener(onChangeListener);
+ mYearSpinnerInput = (EditText) mYearSpinner.findViewById(com.android.internal.R.id.numberpicker_input);
+
+ // show only what the user required but make sure we
+ // show something and the spinners have higher priority
+ if (!spinnersShown && !calendarViewShown) {
+ setSpinnersShown(true);
+ } else {
+ setSpinnersShown(spinnersShown);
+ setCalendarViewShown(calendarViewShown);
+ }
+
+ // set the min date giving priority of the minDate over startYear
+ mTempDate.clear();
+ if (!TextUtils.isEmpty(minDate)) {
+ if (!parseDate(minDate, mTempDate)) {
+ mTempDate.set(startYear, 0, 1);
+ }
+ } else {
+ mTempDate.set(startYear, 0, 1);
+ }
+ setMinDate(mTempDate.getTimeInMillis());
+
+ // set the max date giving priority of the maxDate over endYear
+ mTempDate.clear();
+ if (!TextUtils.isEmpty(maxDate)) {
+ if (!parseDate(maxDate, mTempDate)) {
+ mTempDate.set(endYear, 11, 31);
+ }
+ } else {
+ mTempDate.set(endYear, 11, 31);
+ }
+ setMaxDate(mTempDate.getTimeInMillis());
+
+ // initialize to current date
+ mCurrentDate.setTimeInMillis(System.currentTimeMillis());
+ init(mCurrentDate.get(Calendar.YEAR), mCurrentDate.get(Calendar.MONTH), mCurrentDate
+ .get(Calendar.DAY_OF_MONTH), null);
+
+ // re-order the number spinners to match the current date format
+ reorderSpinners();
+
+ // accessibility
+ setContentDescriptions();
+
+ // If not explicitly specified this view is important for accessibility.
+ if (mDelegator.getImportantForAccessibility() == View.IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
+ mDelegator.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES);
+ }
+ }
+
+ @Override
+ public void init(int year, int monthOfYear, int dayOfMonth,
+ DatePicker.OnDateChangedListener onDateChangedListener) {
+ setDate(year, monthOfYear, dayOfMonth);
+ updateSpinners();
+ updateCalendarView();
+ mOnDateChangedListener = onDateChangedListener;
+ }
+
+ @Override
+ public void updateDate(int year, int month, int dayOfMonth) {
+ if (!isNewDate(year, month, dayOfMonth)) {
+ return;
+ }
+ setDate(year, month, dayOfMonth);
+ updateSpinners();
+ updateCalendarView();
+ notifyDateChanged();
+ }
+
+ @Override
+ public int getYear() {
+ return mCurrentDate.get(Calendar.YEAR);
+ }
+
+ @Override
+ public int getMonth() {
+ return mCurrentDate.get(Calendar.MONTH);
+ }
+
+ @Override
+ public int getDayOfMonth() {
+ return mCurrentDate.get(Calendar.DAY_OF_MONTH);
+ }
+
+ @Override
+ public void setFirstDayOfWeek(int firstDayOfWeek) {
+ mCalendarView.setFirstDayOfWeek(firstDayOfWeek);
+ }
+
+ @Override
+ public int getFirstDayOfWeek() {
+ return mCalendarView.getFirstDayOfWeek();
+ }
+
+ @Override
+ public void setMinDate(long minDate) {
+ mTempDate.setTimeInMillis(minDate);
+ if (mTempDate.get(Calendar.YEAR) == mMinDate.get(Calendar.YEAR)
+ && mTempDate.get(Calendar.DAY_OF_YEAR) != mMinDate.get(Calendar.DAY_OF_YEAR)) {
+ return;
+ }
+ mMinDate.setTimeInMillis(minDate);
+ mCalendarView.setMinDate(minDate);
+ if (mCurrentDate.before(mMinDate)) {
+ mCurrentDate.setTimeInMillis(mMinDate.getTimeInMillis());
+ updateCalendarView();
+ }
+ updateSpinners();
+ }
+
+ @Override
+ public Calendar getMinDate() {
+ final Calendar minDate = Calendar.getInstance();
+ minDate.setTimeInMillis(mCalendarView.getMinDate());
+ return minDate;
+ }
+
+ @Override
+ public void setMaxDate(long maxDate) {
+ mTempDate.setTimeInMillis(maxDate);
+ if (mTempDate.get(Calendar.YEAR) == mMaxDate.get(Calendar.YEAR)
+ && mTempDate.get(Calendar.DAY_OF_YEAR) != mMaxDate.get(Calendar.DAY_OF_YEAR)) {
+ return;
+ }
+ mMaxDate.setTimeInMillis(maxDate);
+ mCalendarView.setMaxDate(maxDate);
+ if (mCurrentDate.after(mMaxDate)) {
+ mCurrentDate.setTimeInMillis(mMaxDate.getTimeInMillis());
+ updateCalendarView();
+ }
+ updateSpinners();
+ }
+
+ @Override
+ public Calendar getMaxDate() {
+ final Calendar maxDate = Calendar.getInstance();
+ maxDate.setTimeInMillis(mCalendarView.getMaxDate());
+ return maxDate;
+ }
+
+ @Override
+ public void setEnabled(boolean enabled) {
+ mDaySpinner.setEnabled(enabled);
+ mMonthSpinner.setEnabled(enabled);
+ mYearSpinner.setEnabled(enabled);
+ mCalendarView.setEnabled(enabled);
+ mIsEnabled = enabled;
+ }
+
+ @Override
+ public boolean isEnabled() {
+ return mIsEnabled;
+ }
+
+ @Override
+ public CalendarView getCalendarView() {
+ return mCalendarView;
+ }
+
+ @Override
+ public void setCalendarViewShown(boolean shown) {
+ mCalendarView.setVisibility(shown ? View.VISIBLE : View.GONE);
+ }
+
+ @Override
+ public boolean getCalendarViewShown() {
+ return (mCalendarView.getVisibility() == View.VISIBLE);
+ }
+
+ @Override
+ public void setSpinnersShown(boolean shown) {
+ mSpinners.setVisibility(shown ? View.VISIBLE : View.GONE);
+ }
+
+ @Override
+ public boolean getSpinnersShown() {
+ return mSpinners.isShown();
+ }
+
+ @Override
+ public void onConfigurationChanged(Configuration newConfig) {
+ setCurrentLocale(newConfig.locale);
+ }
+
+ @Override
+ public Parcelable onSaveInstanceState(Parcelable superState) {
+ return new SavedState(superState, getYear(), getMonth(), getDayOfMonth(),
+ getMinDate().getTimeInMillis(), getMaxDate().getTimeInMillis());
+ }
+
+ @Override
+ public void onRestoreInstanceState(Parcelable state) {
+ if (state instanceof SavedState) {
+ final SavedState ss = (SavedState) state;
+ setDate(ss.getSelectedYear(), ss.getSelectedMonth(), ss.getSelectedDay());
+ updateSpinners();
+ updateCalendarView();
+ }
+ }
+
+ @Override
+ public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
+ onPopulateAccessibilityEvent(event);
+ return true;
+ }
+
+ @Override
+ public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
+ final int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_YEAR;
+ String selectedDateUtterance = DateUtils.formatDateTime(mContext,
+ mCurrentDate.getTimeInMillis(), flags);
+ event.getText().add(selectedDateUtterance);
+ }
+
+ /**
+ * Sets the current locale.
+ *
+ * @param locale The current locale.
+ */
+ @Override
+ protected void setCurrentLocale(Locale locale) {
+ super.setCurrentLocale(locale);
+
+ mTempDate = getCalendarForLocale(mTempDate, locale);
+ mMinDate = getCalendarForLocale(mMinDate, locale);
+ mMaxDate = getCalendarForLocale(mMaxDate, locale);
+ mCurrentDate = getCalendarForLocale(mCurrentDate, locale);
+
+ mNumberOfMonths = mTempDate.getActualMaximum(Calendar.MONTH) + 1;
+ mShortMonths = new DateFormatSymbols().getShortMonths();
+
+ if (usingNumericMonths()) {
+ // We're in a locale where a date should either be all-numeric, or all-text.
+ // All-text would require custom NumberPicker formatters for day and year.
+ mShortMonths = new String[mNumberOfMonths];
+ for (int i = 0; i < mNumberOfMonths; ++i) {
+ mShortMonths[i] = String.format("%d", i + 1);
+ }
+ }
+ }
+
+ /**
+ * Tests whether the current locale is one where there are no real month names,
+ * such as Chinese, Japanese, or Korean locales.
+ */
+ private boolean usingNumericMonths() {
+ return Character.isDigit(mShortMonths[Calendar.JANUARY].charAt(0));
+ }
+
+ /**
+ * Gets a calendar for locale bootstrapped with the value of a given calendar.
+ *
+ * @param oldCalendar The old calendar.
+ * @param locale The locale.
+ */
+ private Calendar getCalendarForLocale(Calendar oldCalendar, Locale locale) {
+ if (oldCalendar == null) {
+ return Calendar.getInstance(locale);
+ } else {
+ final long currentTimeMillis = oldCalendar.getTimeInMillis();
+ Calendar newCalendar = Calendar.getInstance(locale);
+ newCalendar.setTimeInMillis(currentTimeMillis);
+ return newCalendar;
+ }
+ }
+
+ /**
+ * Reorders the spinners according to the date format that is
+ * explicitly set by the user and if no such is set fall back
+ * to the current locale's default format.
+ */
+ private void reorderSpinners() {
+ mSpinners.removeAllViews();
+ // We use numeric spinners for year and day, but textual months. Ask icu4c what
+ // order the user's locale uses for that combination. http://b/7207103.
+ String pattern = DateFormat.getBestDateTimePattern(Locale.getDefault(), "yyyyMMMdd");
+ char[] order = ICU.getDateFormatOrder(pattern);
+ final int spinnerCount = order.length;
+ for (int i = 0; i < spinnerCount; i++) {
+ switch (order[i]) {
+ case 'd':
+ mSpinners.addView(mDaySpinner);
+ setImeOptions(mDaySpinner, spinnerCount, i);
+ break;
+ case 'M':
+ mSpinners.addView(mMonthSpinner);
+ setImeOptions(mMonthSpinner, spinnerCount, i);
+ break;
+ case 'y':
+ mSpinners.addView(mYearSpinner);
+ setImeOptions(mYearSpinner, spinnerCount, i);
+ break;
+ default:
+ throw new IllegalArgumentException(Arrays.toString(order));
+ }
+ }
+ }
+
+ /**
+ * Parses the given <code>date</code> and in case of success sets the result
+ * to the <code>outDate</code>.
+ *
+ * @return True if the date was parsed.
+ */
+ private boolean parseDate(String date, Calendar outDate) {
+ try {
+ outDate.setTime(mDateFormat.parse(date));
+ return true;
+ } catch (ParseException e) {
+ e.printStackTrace();
+ return false;
+ }
+ }
+
+ private boolean isNewDate(int year, int month, int dayOfMonth) {
+ return (mCurrentDate.get(Calendar.YEAR) != year
+ || mCurrentDate.get(Calendar.MONTH) != month
+ || mCurrentDate.get(Calendar.DAY_OF_MONTH) != dayOfMonth);
+ }
+
+ private void setDate(int year, int month, int dayOfMonth) {
+ mCurrentDate.set(year, month, dayOfMonth);
+ if (mCurrentDate.before(mMinDate)) {
+ mCurrentDate.setTimeInMillis(mMinDate.getTimeInMillis());
+ } else if (mCurrentDate.after(mMaxDate)) {
+ mCurrentDate.setTimeInMillis(mMaxDate.getTimeInMillis());
+ }
+ }
+
+ private void updateSpinners() {
+ // set the spinner ranges respecting the min and max dates
+ if (mCurrentDate.equals(mMinDate)) {
+ mDaySpinner.setMinValue(mCurrentDate.get(Calendar.DAY_OF_MONTH));
+ mDaySpinner.setMaxValue(mCurrentDate.getActualMaximum(Calendar.DAY_OF_MONTH));
+ mDaySpinner.setWrapSelectorWheel(false);
+ mMonthSpinner.setDisplayedValues(null);
+ mMonthSpinner.setMinValue(mCurrentDate.get(Calendar.MONTH));
+ mMonthSpinner.setMaxValue(mCurrentDate.getActualMaximum(Calendar.MONTH));
+ mMonthSpinner.setWrapSelectorWheel(false);
+ } else if (mCurrentDate.equals(mMaxDate)) {
+ mDaySpinner.setMinValue(mCurrentDate.getActualMinimum(Calendar.DAY_OF_MONTH));
+ mDaySpinner.setMaxValue(mCurrentDate.get(Calendar.DAY_OF_MONTH));
+ mDaySpinner.setWrapSelectorWheel(false);
+ mMonthSpinner.setDisplayedValues(null);
+ mMonthSpinner.setMinValue(mCurrentDate.getActualMinimum(Calendar.MONTH));
+ mMonthSpinner.setMaxValue(mCurrentDate.get(Calendar.MONTH));
+ mMonthSpinner.setWrapSelectorWheel(false);
+ } else {
+ mDaySpinner.setMinValue(1);
+ mDaySpinner.setMaxValue(mCurrentDate.getActualMaximum(Calendar.DAY_OF_MONTH));
+ mDaySpinner.setWrapSelectorWheel(true);
+ mMonthSpinner.setDisplayedValues(null);
+ mMonthSpinner.setMinValue(0);
+ mMonthSpinner.setMaxValue(11);
+ mMonthSpinner.setWrapSelectorWheel(true);
+ }
+
+ // make sure the month names are a zero based array
+ // with the months in the month spinner
+ String[] displayedValues = Arrays.copyOfRange(mShortMonths,
+ mMonthSpinner.getMinValue(), mMonthSpinner.getMaxValue() + 1);
+ mMonthSpinner.setDisplayedValues(displayedValues);
+
+ // year spinner range does not change based on the current date
+ mYearSpinner.setMinValue(mMinDate.get(Calendar.YEAR));
+ mYearSpinner.setMaxValue(mMaxDate.get(Calendar.YEAR));
+ mYearSpinner.setWrapSelectorWheel(false);
+
+ // set the spinner values
+ mYearSpinner.setValue(mCurrentDate.get(Calendar.YEAR));
+ mMonthSpinner.setValue(mCurrentDate.get(Calendar.MONTH));
+ mDaySpinner.setValue(mCurrentDate.get(Calendar.DAY_OF_MONTH));
+
+ if (usingNumericMonths()) {
+ mMonthSpinnerInput.setRawInputType(InputType.TYPE_CLASS_NUMBER);
+ }
+ }
+
+ /**
+ * Updates the calendar view with the current date.
+ */
+ private void updateCalendarView() {
+ mCalendarView.setDate(mCurrentDate.getTimeInMillis(), false, false);
+ }
+
+
+ /**
+ * Notifies the listener, if such, for a change in the selected date.
+ */
+ private void notifyDateChanged() {
+ mDelegator.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);
+ if (mOnDateChangedListener != null) {
+ mOnDateChangedListener.onDateChanged(mDelegator, getYear(), getMonth(),
+ getDayOfMonth());
+ }
+ }
+
+ /**
+ * Sets the IME options for a spinner based on its ordering.
+ *
+ * @param spinner The spinner.
+ * @param spinnerCount The total spinner count.
+ * @param spinnerIndex The index of the given spinner.
+ */
+ private void setImeOptions(NumberPicker spinner, int spinnerCount, int spinnerIndex) {
+ final int imeOptions;
+ if (spinnerIndex < spinnerCount - 1) {
+ imeOptions = EditorInfo.IME_ACTION_NEXT;
+ } else {
+ imeOptions = EditorInfo.IME_ACTION_DONE;
+ }
+ TextView input = (TextView) spinner.findViewById(com.android.internal.R.id.numberpicker_input);
+ input.setImeOptions(imeOptions);
+ }
+
+ private void setContentDescriptions() {
+ // Day
+ trySetContentDescription(mDaySpinner, com.android.internal.R.id.increment,
+ com.android.internal.R.string.date_picker_increment_day_button);
+ trySetContentDescription(mDaySpinner, com.android.internal.R.id.decrement,
+ com.android.internal.R.string.date_picker_decrement_day_button);
+ // Month
+ trySetContentDescription(mMonthSpinner, com.android.internal.R.id.increment,
+ com.android.internal.R.string.date_picker_increment_month_button);
+ trySetContentDescription(mMonthSpinner, com.android.internal.R.id.decrement,
+ com.android.internal.R.string.date_picker_decrement_month_button);
+ // Year
+ trySetContentDescription(mYearSpinner, com.android.internal.R.id.increment,
+ com.android.internal.R.string.date_picker_increment_year_button);
+ trySetContentDescription(mYearSpinner, com.android.internal.R.id.decrement,
+ com.android.internal.R.string.date_picker_decrement_year_button);
+ }
+
+ private void trySetContentDescription(View root, int viewId, int contDescResId) {
+ View target = root.findViewById(viewId);
+ if (target != null) {
+ target.setContentDescription(mContext.getString(contDescResId));
+ }
+ }
+
+ private void updateInputState() {
+ // Make sure that if the user changes the value and the IME is active
+ // for one of the inputs if this widget, the IME is closed. If the user
+ // changed the value via the IME and there is a next input the IME will
+ // be shown, otherwise the user chose another means of changing the
+ // value and having the IME up makes no sense.
+ InputMethodManager inputMethodManager = InputMethodManager.peekInstance();
+ if (inputMethodManager != null) {
+ if (inputMethodManager.isActive(mYearSpinnerInput)) {
+ mYearSpinnerInput.clearFocus();
+ inputMethodManager.hideSoftInputFromWindow(mDelegator.getWindowToken(), 0);
+ } else if (inputMethodManager.isActive(mMonthSpinnerInput)) {
+ mMonthSpinnerInput.clearFocus();
+ inputMethodManager.hideSoftInputFromWindow(mDelegator.getWindowToken(), 0);
+ } else if (inputMethodManager.isActive(mDaySpinnerInput)) {
+ mDaySpinnerInput.clearFocus();
+ inputMethodManager.hideSoftInputFromWindow(mDelegator.getWindowToken(), 0);
+ }
+ }
+ }
+}
diff --git a/core/java/android/widget/EditText.java b/core/java/android/widget/EditText.java
index 1d242d3..434e3eb 100644
--- a/core/java/android/widget/EditText.java
+++ b/core/java/android/widget/EditText.java
@@ -117,6 +117,16 @@
Selection.extendSelection(getText(), index);
}
+ /**
+ * Causes words in the text that are longer than the view's width to be ellipsized instead of
+ * broken in the middle. {@link TextUtils.TruncateAt#MARQUEE
+ * TextUtils.TruncateAt#MARQUEE} is not supported.
+ *
+ * @param ellipsis Type of ellipsis to be applied.
+ * @throws IllegalArgumentException When the value of <code>ellipsis</code> parameter is
+ * {@link TextUtils.TruncateAt#MARQUEE}.
+ * @see TextView#setEllipsize(TextUtils.TruncateAt)
+ */
@Override
public void setEllipsize(TextUtils.TruncateAt ellipsis) {
if (ellipsis == TextUtils.TruncateAt.MARQUEE) {
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index 881e5cd..e949c52 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -3160,6 +3160,7 @@
mTextView.getContext(), mTextView.mTextEditSuggestionHighlightStyle);
private TextView mAddToDictionaryButton;
private TextView mDeleteButton;
+ private ListView mSuggestionListView;
private SuggestionSpan mMisspelledSpan;
private int mContainerMarginWidth;
private int mContainerMarginTop;
@@ -3177,7 +3178,7 @@
((Spannable) mTextView.getText()).removeSpan(mSuggestionRangeSpan);
mTextView.setCursorVisible(mCursorWasVisibleBeforeSuggestions);
- if (hasInsertionController()) {
+ if (hasInsertionController() && !extractedTextModeWillBeStarted()) {
getInsertionController().show();
}
}
@@ -3213,12 +3214,12 @@
mClippingLimitLeft = lp.leftMargin;
mClippingLimitRight = lp.rightMargin;
- final ListView suggestionListView = (ListView) relativeLayout.findViewById(
+ mSuggestionListView = (ListView) relativeLayout.findViewById(
com.android.internal.R.id.suggestionContainer);
mSuggestionsAdapter = new SuggestionAdapter();
- suggestionListView.setAdapter(mSuggestionsAdapter);
- suggestionListView.setOnItemClickListener(this);
+ mSuggestionListView.setAdapter(mSuggestionsAdapter);
+ mSuggestionListView.setOnItemClickListener(this);
// Inflate the suggestion items once and for all.
mSuggestionInfos = new SuggestionInfo[MAX_NUMBER_SUGGESTIONS];
@@ -3327,6 +3328,9 @@
@Override
public void show() {
if (!(mTextView.getText() instanceof Editable)) return;
+ if (extractedTextModeWillBeStarted()) {
+ return;
+ }
if (updateSuggestions()) {
mCursorWasVisibleBeforeSuggestions = mCursorVisible;
@@ -3374,6 +3378,7 @@
popupBackground.getPadding(mTempRect);
width += mTempRect.left + mTempRect.right;
}
+ mSuggestionListView.getLayoutParams().width = width;
mPopupWindow.setWidth(width);
}
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index f19bf02..18f1ae5 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -20,6 +20,7 @@
import android.R;
import android.annotation.ColorInt;
import android.annotation.DrawableRes;
+import android.annotation.FloatRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.Size;
@@ -5835,8 +5836,7 @@
final int layoutDirection = getLayoutDirection();
final int absoluteGravity = Gravity.getAbsoluteGravity(mGravity, layoutDirection);
- if (mEllipsize == TextUtils.TruncateAt.MARQUEE &&
- mMarqueeFadeMode != MARQUEE_FADE_SWITCH_SHOW_ELLIPSIS) {
+ if (isMarqueeFadeEnabled()) {
if (!mSingleLine && getLineCount() == 1 && canMarquee() &&
(absoluteGravity & Gravity.HORIZONTAL_GRAVITY_MASK) != Gravity.LEFT) {
final int width = mRight - mLeft;
@@ -7888,7 +7888,7 @@
}
/**
- * Causes words in the text that are longer than the view is wide
+ * Causes words in the text that are longer than the view's width
* to be ellipsized instead of broken in the middle. You may also
* want to {@link #setSingleLine} or {@link #setHorizontallyScrolling}
* to constrain the text to a single line. Use <code>null</code>
@@ -8616,78 +8616,59 @@
@Override
protected float getLeftFadingEdgeStrength() {
- if (mEllipsize == TextUtils.TruncateAt.MARQUEE &&
- mMarqueeFadeMode != MARQUEE_FADE_SWITCH_SHOW_ELLIPSIS) {
- if (mMarquee != null && !mMarquee.isStopped()) {
- final Marquee marquee = mMarquee;
- if (marquee.shouldDrawLeftFade()) {
- final float scroll = marquee.getScroll();
- return scroll / getHorizontalFadingEdgeLength();
- } else {
- return 0.0f;
- }
- } else if (getLineCount() == 1) {
- final int layoutDirection = getLayoutDirection();
- final int absoluteGravity = Gravity.getAbsoluteGravity(mGravity, layoutDirection);
- switch (absoluteGravity & Gravity.HORIZONTAL_GRAVITY_MASK) {
- case Gravity.LEFT:
- return 0.0f;
- case Gravity.RIGHT:
- return (mLayout.getLineRight(0) - (mRight - mLeft) -
- getCompoundPaddingLeft() - getCompoundPaddingRight() -
- mLayout.getLineLeft(0)) / getHorizontalFadingEdgeLength();
- case Gravity.CENTER_HORIZONTAL:
- case Gravity.FILL_HORIZONTAL:
- final int textDirection = mLayout.getParagraphDirection(0);
- if (textDirection == Layout.DIR_LEFT_TO_RIGHT) {
- return 0.0f;
- } else {
- return (mLayout.getLineRight(0) - (mRight - mLeft) -
- getCompoundPaddingLeft() - getCompoundPaddingRight() -
- mLayout.getLineLeft(0)) / getHorizontalFadingEdgeLength();
- }
- }
+ if (isMarqueeFadeEnabled() && mMarquee != null && !mMarquee.isStopped()) {
+ final Marquee marquee = mMarquee;
+ if (marquee.shouldDrawLeftFade()) {
+ return getHorizontalFadingEdgeStrength(marquee.getScroll(), 0.0f);
+ } else {
+ return 0.0f;
}
+ } else if (getLineCount() == 1) {
+ final float lineLeft = getLayout().getLineLeft(0);
+ if(lineLeft > mScrollX) return 0.0f;
+ return getHorizontalFadingEdgeStrength(mScrollX, lineLeft);
}
return super.getLeftFadingEdgeStrength();
}
@Override
protected float getRightFadingEdgeStrength() {
- if (mEllipsize == TextUtils.TruncateAt.MARQUEE &&
- mMarqueeFadeMode != MARQUEE_FADE_SWITCH_SHOW_ELLIPSIS) {
- if (mMarquee != null && !mMarquee.isStopped()) {
- final Marquee marquee = mMarquee;
- final float maxFadeScroll = marquee.getMaxFadeScroll();
- final float scroll = marquee.getScroll();
- return (maxFadeScroll - scroll) / getHorizontalFadingEdgeLength();
- } else if (getLineCount() == 1) {
- final int layoutDirection = getLayoutDirection();
- final int absoluteGravity = Gravity.getAbsoluteGravity(mGravity, layoutDirection);
- switch (absoluteGravity & Gravity.HORIZONTAL_GRAVITY_MASK) {
- case Gravity.LEFT:
- final int textWidth = (mRight - mLeft) - getCompoundPaddingLeft() -
- getCompoundPaddingRight();
- final float lineWidth = mLayout.getLineWidth(0);
- return (lineWidth - textWidth) / getHorizontalFadingEdgeLength();
- case Gravity.RIGHT:
- return 0.0f;
- case Gravity.CENTER_HORIZONTAL:
- case Gravity.FILL_HORIZONTAL:
- final int textDirection = mLayout.getParagraphDirection(0);
- if (textDirection == Layout.DIR_RIGHT_TO_LEFT) {
- return 0.0f;
- } else {
- return (mLayout.getLineWidth(0) - ((mRight - mLeft) -
- getCompoundPaddingLeft() - getCompoundPaddingRight())) /
- getHorizontalFadingEdgeLength();
- }
- }
- }
+ if (isMarqueeFadeEnabled() && mMarquee != null && !mMarquee.isStopped()) {
+ final Marquee marquee = mMarquee;
+ return getHorizontalFadingEdgeStrength(marquee.getMaxFadeScroll(), marquee.getScroll());
+ } else if (getLineCount() == 1) {
+ final float rightEdge = mScrollX + (getWidth() - getCompoundPaddingLeft() -
+ getCompoundPaddingRight());
+ final float lineRight = getLayout().getLineRight(0);
+ if(lineRight < rightEdge) return 0.0f;
+ return getHorizontalFadingEdgeStrength(rightEdge, lineRight);
}
return super.getRightFadingEdgeStrength();
}
+ /**
+ * Calculates the fading edge strength as the ratio of the distance between two
+ * horizontal positions to {@link View#getHorizontalFadingEdgeLength()}. Uses the absolute
+ * value for the distance calculation.
+ *
+ * @param position1 A horizontal position.
+ * @param position2 A horizontal position.
+ * @return Fading edge strength between [0.0f, 1.0f].
+ */
+ @FloatRange(from=0.0, to=1.0)
+ private final float getHorizontalFadingEdgeStrength(float position1, float position2) {
+ final int horizontalFadingEdgeLength = getHorizontalFadingEdgeLength();
+ if(horizontalFadingEdgeLength == 0) return 0.0f;
+ final float diff = Math.abs(position1 - position2);
+ if(diff > horizontalFadingEdgeLength) return 1.0f;
+ return diff / horizontalFadingEdgeLength;
+ }
+
+ private final boolean isMarqueeFadeEnabled() {
+ return mEllipsize == TextUtils.TruncateAt.MARQUEE &&
+ mMarqueeFadeMode != MARQUEE_FADE_SWITCH_SHOW_ELLIPSIS;
+ }
+
@Override
protected int computeHorizontalScrollRange() {
if (mLayout != null) {
diff --git a/core/java/android/widget/TimePicker.java b/core/java/android/widget/TimePicker.java
index a24d37f..f2fc617 100644
--- a/core/java/android/widget/TimePicker.java
+++ b/core/java/android/widget/TimePicker.java
@@ -22,8 +22,11 @@
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.TypedArray;
+import android.os.Parcel;
import android.os.Parcelable;
+import android.os.Parcelable.Creator;
import android.util.AttributeSet;
+import android.view.View;
import android.view.accessibility.AccessibilityEvent;
import com.android.internal.R;
@@ -301,5 +304,69 @@
mContext = context;
mLocale = context.getResources().getConfiguration().locale;
}
+
+ protected static class SavedState extends View.BaseSavedState {
+ private final int mHour;
+ private final int mMinute;
+ private final boolean mIs24HourMode;
+ private final int mCurrentItemShowing;
+
+ public SavedState(Parcelable superState, int hour, int minute, boolean is24HourMode) {
+ this(superState, hour, minute, is24HourMode, 0);
+ }
+
+ public SavedState(Parcelable superState, int hour, int minute, boolean is24HourMode,
+ int currentItemShowing) {
+ super(superState);
+ mHour = hour;
+ mMinute = minute;
+ mIs24HourMode = is24HourMode;
+ mCurrentItemShowing = currentItemShowing;
+ }
+
+ private SavedState(Parcel in) {
+ super(in);
+ mHour = in.readInt();
+ mMinute = in.readInt();
+ mIs24HourMode = (in.readInt() == 1);
+ mCurrentItemShowing = in.readInt();
+ }
+
+ public int getHour() {
+ return mHour;
+ }
+
+ public int getMinute() {
+ return mMinute;
+ }
+
+ public boolean is24HourMode() {
+ return mIs24HourMode;
+ }
+
+ public int getCurrentItemShowing() {
+ return mCurrentItemShowing;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ super.writeToParcel(dest, flags);
+ dest.writeInt(mHour);
+ dest.writeInt(mMinute);
+ dest.writeInt(mIs24HourMode ? 1 : 0);
+ dest.writeInt(mCurrentItemShowing);
+ }
+
+ @SuppressWarnings({"unused", "hiding"})
+ public static final Creator<SavedState> CREATOR = new Creator<SavedState>() {
+ public SavedState createFromParcel(Parcel in) {
+ return new SavedState(in);
+ }
+
+ public SavedState[] newArray(int size) {
+ return new SavedState[size];
+ }
+ };
+ }
}
}
diff --git a/core/java/android/widget/TimePickerClockDelegate.java b/core/java/android/widget/TimePickerClockDelegate.java
index 05fd4c8..4a24e26 100644
--- a/core/java/android/widget/TimePickerClockDelegate.java
+++ b/core/java/android/widget/TimePickerClockDelegate.java
@@ -21,7 +21,6 @@
import android.content.res.ColorStateList;
import android.content.res.Resources;
import android.content.res.TypedArray;
-import android.os.Parcel;
import android.os.Parcelable;
import android.text.SpannableStringBuilder;
import android.text.format.DateFormat;
@@ -45,7 +44,6 @@
import com.android.internal.widget.NumericTextView.OnValueChangedListener;
import java.util.Calendar;
-import java.util.Locale;
/**
* A delegate implementing the radial clock-based TimePicker.
@@ -501,9 +499,11 @@
@Override
public void onRestoreInstanceState(Parcelable state) {
- final SavedState ss = (SavedState) state;
- initialize(ss.getHour(), ss.getMinute(), ss.is24HourMode(), ss.getCurrentItemShowing());
- mRadialTimePickerView.invalidate();
+ if (state instanceof SavedState) {
+ final SavedState ss = (SavedState) state;
+ initialize(ss.getHour(), ss.getMinute(), ss.is24HourMode(), ss.getCurrentItemShowing());
+ mRadialTimePickerView.invalidate();
+ }
}
@Override
@@ -544,70 +544,6 @@
}
}
- /**
- * Used to save / restore state of time picker
- */
- private static class SavedState extends View.BaseSavedState {
-
- private final int mHour;
- private final int mMinute;
- private final boolean mIs24HourMode;
- private final int mCurrentItemShowing;
-
- private SavedState(Parcelable superState, int hour, int minute, boolean is24HourMode,
- int currentItemShowing) {
- super(superState);
- mHour = hour;
- mMinute = minute;
- mIs24HourMode = is24HourMode;
- mCurrentItemShowing = currentItemShowing;
- }
-
- private SavedState(Parcel in) {
- super(in);
- mHour = in.readInt();
- mMinute = in.readInt();
- mIs24HourMode = (in.readInt() == 1);
- mCurrentItemShowing = in.readInt();
- }
-
- public int getHour() {
- return mHour;
- }
-
- public int getMinute() {
- return mMinute;
- }
-
- public boolean is24HourMode() {
- return mIs24HourMode;
- }
-
- public int getCurrentItemShowing() {
- return mCurrentItemShowing;
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- super.writeToParcel(dest, flags);
- dest.writeInt(mHour);
- dest.writeInt(mMinute);
- dest.writeInt(mIs24HourMode ? 1 : 0);
- dest.writeInt(mCurrentItemShowing);
- }
-
- @SuppressWarnings({"unused", "hiding"})
- public static final Creator<SavedState> CREATOR = new Creator<SavedState>() {
- public SavedState createFromParcel(Parcel in) {
- return new SavedState(in);
- }
-
- public SavedState[] newArray(int size) {
- return new SavedState[size];
- }
- };
- }
-
private void tryVibrate() {
mDelegator.performHapticFeedback(HapticFeedbackConstants.CLOCK_TICK);
}
diff --git a/core/java/android/widget/TimePickerSpinnerDelegate.java b/core/java/android/widget/TimePickerSpinnerDelegate.java
index 863d409..b113fd9 100644
--- a/core/java/android/widget/TimePickerSpinnerDelegate.java
+++ b/core/java/android/widget/TimePickerSpinnerDelegate.java
@@ -18,7 +18,6 @@
import android.content.Context;
import android.content.res.TypedArray;
-import android.os.Parcel;
import android.os.Parcelable;
import android.text.format.DateFormat;
import android.text.format.DateUtils;
@@ -32,7 +31,6 @@
import com.android.internal.R;
import java.util.Calendar;
-import java.util.Locale;
import libcore.icu.LocaleData;
@@ -387,14 +385,16 @@
@Override
public Parcelable onSaveInstanceState(Parcelable superState) {
- return new SavedState(superState, getHour(), getMinute());
+ return new SavedState(superState, getHour(), getMinute(), is24Hour());
}
@Override
public void onRestoreInstanceState(Parcelable state) {
- SavedState ss = (SavedState) state;
- setHour(ss.getHour());
- setMinute(ss.getMinute());
+ if (state instanceof SavedState) {
+ final SavedState ss = (SavedState) state;
+ setHour(ss.getHour());
+ setMinute(ss.getMinute());
+ }
}
@Override
@@ -525,52 +525,6 @@
}
}
- /**
- * Used to save / restore state of time picker
- */
- private static class SavedState extends View.BaseSavedState {
- private final int mHour;
- private final int mMinute;
-
- private SavedState(Parcelable superState, int hour, int minute) {
- super(superState);
- mHour = hour;
- mMinute = minute;
- }
-
- private SavedState(Parcel in) {
- super(in);
- mHour = in.readInt();
- mMinute = in.readInt();
- }
-
- public int getHour() {
- return mHour;
- }
-
- public int getMinute() {
- return mMinute;
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- super.writeToParcel(dest, flags);
- dest.writeInt(mHour);
- dest.writeInt(mMinute);
- }
-
- @SuppressWarnings({"unused", "hiding"})
- public static final Parcelable.Creator<SavedState> CREATOR = new Creator<SavedState>() {
- public SavedState createFromParcel(Parcel in) {
- return new SavedState(in);
- }
-
- public SavedState[] newArray(int size) {
- return new SavedState[size];
- }
- };
- }
-
public static String[] getAmPmStrings(Context context) {
String[] result = new String[2];
LocaleData d = LocaleData.get(context.getResources().getConfiguration().locale);
diff --git a/core/java/com/android/internal/app/LocaleHelper.java b/core/java/com/android/internal/app/LocaleHelper.java
index aca93ab..d8d6e56 100644
--- a/core/java/com/android/internal/app/LocaleHelper.java
+++ b/core/java/com/android/internal/app/LocaleHelper.java
@@ -180,14 +180,16 @@
*/
public static final class LocaleInfoComparator implements Comparator<LocaleStore.LocaleInfo> {
private final Collator mCollator;
+ private final boolean mCountryMode;
/**
* Constructor.
*
* @param sortLocale the locale to be used for sorting.
*/
- public LocaleInfoComparator(Locale sortLocale) {
+ public LocaleInfoComparator(Locale sortLocale, boolean countryMode) {
mCollator = Collator.getInstance(sortLocale);
+ mCountryMode = countryMode;
}
/**
@@ -202,9 +204,9 @@
public int compare(LocaleStore.LocaleInfo lhs, LocaleStore.LocaleInfo rhs) {
// We don't care about the various suggestion types, just "suggested" (!= 0)
// and "all others" (== 0)
- if (lhs.isSuggested() == rhs.isSuggested()) {
+ if (mCountryMode || (lhs.isSuggested() == rhs.isSuggested())) {
// They are in the same "bucket" (suggested / others), so we compare the text
- return mCollator.compare(lhs.getLabel(), rhs.getLabel());
+ return mCollator.compare(lhs.getLabel(mCountryMode), rhs.getLabel(mCountryMode));
} else {
// One locale is suggested and one is not, so we put them in different "buckets"
return lhs.isSuggested() ? -1 : 1;
diff --git a/core/java/com/android/internal/app/LocalePickerWithRegion.java b/core/java/com/android/internal/app/LocalePickerWithRegion.java
index 956ee8c..2ea225f 100644
--- a/core/java/com/android/internal/app/LocalePickerWithRegion.java
+++ b/core/java/com/android/internal/app/LocalePickerWithRegion.java
@@ -50,7 +50,6 @@
private Set<LocaleStore.LocaleInfo> mLocaleList;
private LocaleStore.LocaleInfo mParentLocale;
private boolean mTranslatedOnly = false;
- private boolean mCountryMode = false;
/**
* Other classes can register to be notified when a locale was selected.
@@ -70,15 +69,14 @@
boolean translatedOnly) {
LocalePickerWithRegion localePicker = new LocalePickerWithRegion();
boolean shouldShowTheList = localePicker.setListener(context, listener, parent,
- true /* country mode */, translatedOnly);
+ translatedOnly);
return shouldShowTheList ? localePicker : null;
}
public static LocalePickerWithRegion createLanguagePicker(Context context,
LocaleSelectedListener listener, boolean translatedOnly) {
LocalePickerWithRegion localePicker = new LocalePickerWithRegion();
- localePicker.setListener(context, listener, null,
- false /* language mode */, translatedOnly);
+ localePicker.setListener(context, listener, /* parent */ null, translatedOnly);
return localePicker;
}
@@ -96,14 +94,7 @@
* "pretending" it was selected, and return false.</p>
*/
private boolean setListener(Context context, LocaleSelectedListener listener,
- LocaleStore.LocaleInfo parent, boolean countryMode, boolean translatedOnly) {
- if (countryMode && (parent == null || parent.getLocale() == null)) {
- // The list of countries is determined as all the countries where the parent language
- // is used.
- throw new IllegalArgumentException("The country selection list needs a parent.");
- }
-
- this.mCountryMode = countryMode;
+ LocaleStore.LocaleInfo parent, boolean translatedOnly) {
this.mParentLocale = parent;
this.mListener = listener;
this.mTranslatedOnly = translatedOnly;
@@ -116,7 +107,7 @@
Collections.addAll(langTagsToIgnore, langTags);
}
- if (countryMode) {
+ if (parent != null) {
mLocaleList = LocaleStore.getLevelLocales(context,
langTagsToIgnore, parent, translatedOnly);
if (mLocaleList.size() <= 1) {
@@ -138,13 +129,11 @@
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
- final Locale sortingLocale = (mCountryMode && mParentLocale != null)
- ? mParentLocale.getLocale()
- : Locale.getDefault();
-
- mAdapter = new SuggestedLocaleAdapter(mLocaleList, mCountryMode);
+ final boolean countryMode = mParentLocale != null;
+ final Locale sortingLocale = countryMode ? mParentLocale.getLocale() : Locale.getDefault();
+ mAdapter = new SuggestedLocaleAdapter(mLocaleList, countryMode);
final LocaleHelper.LocaleInfoComparator comp =
- new LocaleHelper.LocaleInfoComparator(sortingLocale);
+ new LocaleHelper.LocaleInfoComparator(sortingLocale, countryMode);
mAdapter.sort(comp);
setListAdapter(mAdapter);
}
@@ -164,12 +153,8 @@
public void onResume() {
super.onResume();
- if (mCountryMode) {
- if (mParentLocale == null) {
- this.getActivity().setTitle(R.string.country_selection_title);
- } else {
- this.getActivity().setTitle(mParentLocale.getFullNameNative());
- }
+ if (mParentLocale != null) {
+ this.getActivity().setTitle(mParentLocale.getFullNameNative());
} else {
this.getActivity().setTitle(R.string.language_selection_title);
}
@@ -182,7 +167,7 @@
final LocaleStore.LocaleInfo locale =
(LocaleStore.LocaleInfo) getListAdapter().getItem(position);
- if (mCountryMode || locale.getParent() != null) {
+ if (locale.getParent() != null) {
if (mListener != null) {
mListener.onLocaleSelected(locale);
}
@@ -205,7 +190,7 @@
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
- if (!mCountryMode) {
+ if (mParentLocale == null) {
inflater.inflate(R.menu.language_selection_list, menu);
MenuItem mSearchMenuItem = menu.findItem(R.id.locale_search_menu);
diff --git a/core/java/com/android/internal/app/LocaleStore.java b/core/java/com/android/internal/app/LocaleStore.java
index 465c4d8..c4e6675 100644
--- a/core/java/com/android/internal/app/LocaleStore.java
+++ b/core/java/com/android/internal/app/LocaleStore.java
@@ -145,11 +145,11 @@
return mLangScriptKey;
}
- String getLabel() {
- if (getParent() == null || this.isSuggestionOfType(SUGGESTION_TYPE_SIM)) {
- return getFullNameNative();
- } else {
+ String getLabel(boolean countryMode) {
+ if (countryMode) {
return getFullCountryNameNative();
+ } else {
+ return getFullNameNative();
}
}
@@ -311,9 +311,7 @@
if (level == 2) {
if (parent != null) { // region selection
if (parentId.equals(li.getParent().toLanguageTag())) {
- if (!li.isSuggestionOfType(LocaleInfo.SUGGESTION_TYPE_SIM)) {
- result.add(li);
- }
+ result.add(li);
}
} else { // language selection
if (li.isSuggestionOfType(LocaleInfo.SUGGESTION_TYPE_SIM)) {
diff --git a/core/java/com/android/internal/app/SuggestedLocaleAdapter.java b/core/java/com/android/internal/app/SuggestedLocaleAdapter.java
index 0d4a5aa..98102ea 100644
--- a/core/java/com/android/internal/app/SuggestedLocaleAdapter.java
+++ b/core/java/com/android/internal/app/SuggestedLocaleAdapter.java
@@ -156,7 +156,7 @@
TextView text = (TextView) convertView.findViewById(R.id.locale);
LocaleStore.LocaleInfo item = (LocaleStore.LocaleInfo) getItem(position);
- text.setText(item.getLabel());
+ text.setText(item.getLabel(mCountryMode));
text.setTextLocale(item.getLocale());
if (mCountryMode) {
int layoutDir = TextUtils.getLayoutDirectionFromLocale(item.getParent());
@@ -171,6 +171,9 @@
}
private boolean showHeaders() {
+ if (mCountryMode) { // never show suggestions in country mode
+ return false;
+ }
return mSuggestionCount != 0 && mSuggestionCount != mLocaleOptions.size();
}
diff --git a/core/java/com/android/internal/inputmethod/InputMethodUtils.java b/core/java/com/android/internal/inputmethod/InputMethodUtils.java
index 4e48e45..f04bcf2 100644
--- a/core/java/com/android/internal/inputmethod/InputMethodUtils.java
+++ b/core/java/com/android/internal/inputmethod/InputMethodUtils.java
@@ -547,23 +547,25 @@
LocaleUtils.filterByLanguage(keyboardSubtypes, sSubtypeToLocale, systemLocales,
applicableSubtypes);
- boolean hasAsciiCapableKeyboard = false;
- final int numApplicationSubtypes = applicableSubtypes.size();
- for (int i = 0; i < numApplicationSubtypes; ++i) {
- final InputMethodSubtype subtype = applicableSubtypes.get(i);
- if (subtype.containsExtraValueKey(TAG_ASCII_CAPABLE)) {
- hasAsciiCapableKeyboard = true;
- break;
+ if (!applicableSubtypes.isEmpty()) {
+ boolean hasAsciiCapableKeyboard = false;
+ final int numApplicationSubtypes = applicableSubtypes.size();
+ for (int i = 0; i < numApplicationSubtypes; ++i) {
+ final InputMethodSubtype subtype = applicableSubtypes.get(i);
+ if (subtype.containsExtraValueKey(TAG_ASCII_CAPABLE)) {
+ hasAsciiCapableKeyboard = true;
+ break;
+ }
}
- }
- if (!hasAsciiCapableKeyboard) {
- final int numKeyboardSubtypes = keyboardSubtypes.size();
- for (int i = 0; i < numKeyboardSubtypes; ++i) {
- final InputMethodSubtype subtype = keyboardSubtypes.get(i);
- final String mode = subtype.getMode();
- if (SUBTYPE_MODE_KEYBOARD.equals(mode) && subtype.containsExtraValueKey(
- TAG_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE)) {
- applicableSubtypes.add(subtype);
+ if (!hasAsciiCapableKeyboard) {
+ final int numKeyboardSubtypes = keyboardSubtypes.size();
+ for (int i = 0; i < numKeyboardSubtypes; ++i) {
+ final InputMethodSubtype subtype = keyboardSubtypes.get(i);
+ final String mode = subtype.getMode();
+ if (SUBTYPE_MODE_KEYBOARD.equals(mode) && subtype.containsExtraValueKey(
+ TAG_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE)) {
+ applicableSubtypes.add(subtype);
+ }
}
}
}
diff --git a/core/java/com/android/internal/os/BatteryStatsHelper.java b/core/java/com/android/internal/os/BatteryStatsHelper.java
index f178c8c..1b52146 100644
--- a/core/java/com/android/internal/os/BatteryStatsHelper.java
+++ b/core/java/com/android/internal/os/BatteryStatsHelper.java
@@ -754,8 +754,7 @@
try {
ParcelFileDescriptor pfd = service.getStatisticsStream();
if (pfd != null) {
- FileInputStream fis = new ParcelFileDescriptor.AutoCloseInputStream(pfd);
- try {
+ try (FileInputStream fis = new ParcelFileDescriptor.AutoCloseInputStream(pfd)) {
byte[] data = readFully(fis, MemoryFile.getSize(pfd.getFileDescriptor()));
Parcel parcel = Parcel.obtain();
parcel.unmarshall(data, 0, data.length);
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index eb509c2..3abea26 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -499,11 +499,11 @@
try {
for (String classPathElement : classPathElements) {
+ // System server is fully AOTed and never profiled
+ // for profile guided compilation.
final int dexoptNeeded = DexFile.getDexOptNeeded(
- classPathElement, "*", instructionSet, false /* defer */);
+ classPathElement, instructionSet, DexFile.COMPILATION_TYPE_FULL);
if (dexoptNeeded != DexFile.NO_DEXOPT_NEEDED) {
- // System server is fully AOTed and never profiled
- // for profile guided compilation.
installer.dexopt(classPathElement, Process.SYSTEM_UID, instructionSet,
dexoptNeeded, 0 /*dexFlags*/, null /*volumeUuid*/,
false /*useProfiles*/);
diff --git a/core/java/com/android/internal/util/WakeupMessage.java b/core/java/com/android/internal/util/WakeupMessage.java
index 451078b..2653745 100644
--- a/core/java/com/android/internal/util/WakeupMessage.java
+++ b/core/java/com/android/internal/util/WakeupMessage.java
@@ -21,7 +21,9 @@
import android.os.Handler;
import android.os.Message;
-/**
+import com.android.internal.annotations.VisibleForTesting;
+
+ /**
* An AlarmListener that sends the specified message to a Handler and keeps the system awake until
* the message is processed.
*
@@ -36,9 +38,13 @@
*/
public class WakeupMessage implements AlarmManager.OnAlarmListener {
private final AlarmManager mAlarmManager;
- private final Handler mHandler;
- private final String mCmdName;
- private final int mCmd, mArg1, mArg2;
+
+ @VisibleForTesting
+ protected final Handler mHandler;
+ @VisibleForTesting
+ protected final String mCmdName;
+ @VisibleForTesting
+ protected final int mCmd, mArg1, mArg2;
private boolean mScheduled;
public WakeupMessage(Context context, Handler handler,
diff --git a/core/java/com/android/internal/widget/ImageFloatingTextView.java b/core/java/com/android/internal/widget/ImageFloatingTextView.java
index c4ed2e1..78c5e34 100644
--- a/core/java/com/android/internal/widget/ImageFloatingTextView.java
+++ b/core/java/com/android/internal/widget/ImageFloatingTextView.java
@@ -65,6 +65,8 @@
.setTextDirection(getTextDirectionHeuristic())
.setLineSpacing(getLineSpacingExtra(), getLineSpacingMultiplier())
.setIncludePad(getIncludeFontPadding())
+ .setEllipsize(shouldEllipsize ? effectiveEllipsize : null)
+ .setEllipsizedWidth(ellipsisWidth)
.setBreakStrategy(Layout.BREAK_STRATEGY_HIGH_QUALITY)
.setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_FULL);
// we set the endmargin on the first 2 lines. this works just in our case but that's
diff --git a/core/java/com/android/server/net/NetworkPinner.java b/core/java/com/android/server/net/NetworkPinner.java
new file mode 100644
index 0000000..d922a48
--- /dev/null
+++ b/core/java/com/android/server/net/NetworkPinner.java
@@ -0,0 +1,146 @@
+/*
+ * 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.
+ */
+
+package com.android.server.net;
+
+import android.content.Context;
+import android.net.ConnectivityManager;
+import android.net.ConnectivityManager.NetworkCallback;
+import android.net.Network;
+import android.net.NetworkRequest;
+import android.util.Log;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
+
+/**
+ * A class that pins a process to the first network that satisfies a particular NetworkRequest.
+ *
+ * We use this to maintain compatibility with pre-M apps that call WifiManager.enableNetwork()
+ * to connect to a Wi-Fi network that has no Internet access, and then assume that they will be
+ * able to use that network because it's the system default.
+ *
+ * In order to maintain compatibility with apps that call setProcessDefaultNetwork themselves,
+ * we try not to set the default network unless they have already done so, and we try not to
+ * clear the default network unless we set it ourselves.
+ *
+ * This should maintain behaviour that's compatible with L, which would pin the whole system to
+ * any wifi network that was created via enableNetwork(..., true) until that network
+ * disconnected.
+ *
+ * Note that while this hack allows network traffic to flow, it is quite limited. For example:
+ *
+ * 1. setProcessDefaultNetwork only affects this process, so:
+ * - Any subprocesses spawned by this process will not be pinned to Wi-Fi.
+ * - If this app relies on any other apps on the device also being on Wi-Fi, that won't work
+ * either, because other apps on the device will not be pinned.
+ * 2. The behaviour of other APIs is not modified. For example:
+ * - getActiveNetworkInfo will return the system default network, not Wi-Fi.
+ * - There will be no CONNECTIVITY_ACTION broadcasts about TYPE_WIFI.
+ * - getProcessDefaultNetwork will not return null, so if any apps are relying on that, they
+ * will be surprised as well.
+ *
+ * This class is a per-process singleton because the process default network is a per-process
+ * singleton.
+ *
+ */
+public class NetworkPinner extends NetworkCallback {
+
+ private static final String TAG = NetworkPinner.class.getSimpleName();
+
+ @VisibleForTesting
+ protected static final Object sLock = new Object();
+
+ @GuardedBy("sLock")
+ private static ConnectivityManager sCM;
+ @GuardedBy("sLock")
+ private static Callback sCallback;
+ @VisibleForTesting
+ @GuardedBy("sLock")
+ protected static Network sNetwork;
+
+ private static void maybeInitConnectivityManager(Context context) {
+ // TODO: what happens if an app calls a WifiManager API before ConnectivityManager is
+ // registered? Can we fix this by starting ConnectivityService before WifiService?
+ if (sCM == null) {
+ // Getting a ConnectivityManager does not leak the calling context, because it stores
+ // the application context and not the calling context.
+ sCM = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
+ if (sCM == null) {
+ throw new IllegalStateException("Bad luck, ConnectivityService not started.");
+ }
+ }
+ }
+
+ private static class Callback extends NetworkCallback {
+ @Override
+ public void onAvailable(Network network) {
+ synchronized(sLock) {
+ if (this != sCallback) return;
+
+ if (sCM.getBoundNetworkForProcess() == null && sNetwork == null) {
+ sCM.bindProcessToNetwork(network);
+ sNetwork = network;
+ Log.d(TAG, "Wifi alternate reality enabled on network " + network);
+ }
+ sLock.notify();
+ }
+ }
+
+ @Override
+ public void onLost(Network network) {
+ synchronized (sLock) {
+ if (this != sCallback) return;
+
+ if (network.equals(sNetwork) && network.equals(sCM.getBoundNetworkForProcess())) {
+ unpin();
+ Log.d(TAG, "Wifi alternate reality disabled on network " + network);
+ }
+ sLock.notify();
+ }
+ }
+ }
+
+ public static void pin(Context context, NetworkRequest request) {
+ synchronized (sLock) {
+ if (sCallback == null) {
+ maybeInitConnectivityManager(context);
+ sCallback = new Callback();
+ try {
+ sCM.registerNetworkCallback(request, sCallback);
+ } catch (SecurityException e) {
+ Log.d(TAG, "Failed to register network callback", e);
+ sCallback = null;
+ }
+ }
+ }
+ }
+
+ public static void unpin() {
+ synchronized (sLock) {
+ if (sCallback != null) {
+ try {
+ sCM.bindProcessToNetwork(null);
+ sCM.unregisterNetworkCallback(sCallback);
+ } catch (SecurityException e) {
+ Log.d(TAG, "Failed to unregister network callback", e);
+ }
+ sCallback = null;
+ sNetwork = null;
+ }
+ }
+ }
+}
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index ed3fe42..816a2c4 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -190,7 +190,6 @@
$(call include-path-for, bluedroid) \
$(call include-path-for, libhardware)/hardware \
$(call include-path-for, libhardware_legacy)/hardware_legacy \
- $(TOP)/frameworks/av/include \
$(TOP)/frameworks/base/media/jni \
$(TOP)/system/core/base/include \
$(TOP)/system/core/include \
diff --git a/core/jni/android_app_Activity.cpp b/core/jni/android_app_Activity.cpp
index b1d7e82..56f4f01 100644
--- a/core/jni/android_app_Activity.cpp
+++ b/core/jni/android_app_Activity.cpp
@@ -15,16 +15,25 @@
*/
#include <poll.h>
-#include <android/dlext.h>
+
+#include <string>
#include "core_jni_helpers.h"
+extern "C" void android_dlwarning(void*, void (*)(void*, const char*));
+
namespace android
{
static jstring getDlWarning_native(JNIEnv* env, jobject) {
- const char* text = android_dlwarning();
- return text == nullptr ? nullptr : env->NewStringUTF(text);
+ std::string msg;
+ android_dlwarning(&msg, [](void* obj, const char* msg) {
+ if (msg != nullptr) {
+ *reinterpret_cast<std::string*>(obj) = msg;
+ }
+ });
+
+ return msg.empty() ? nullptr : env->NewStringUTF(msg.c_str());
}
static const JNINativeMethod g_methods[] = {
diff --git a/core/jni/android_hardware_camera2_CameraMetadata.cpp b/core/jni/android_hardware_camera2_CameraMetadata.cpp
index 7930027..f37fd78 100644
--- a/core/jni/android_hardware_camera2_CameraMetadata.cpp
+++ b/core/jni/android_hardware_camera2_CameraMetadata.cpp
@@ -33,9 +33,9 @@
#include "core_jni_helpers.h"
#include "android_runtime/android_hardware_camera2_CameraMetadata.h"
+#include <android/hardware/ICameraService.h>
#include <binder/IServiceManager.h>
#include <camera/CameraMetadata.h>
-#include <camera/ICameraService.h>
#include <camera/VendorTagDescriptor.h>
#include <nativehelper/ScopedUtfChars.h>
#include <nativehelper/ScopedPrimitiveArray.h>
@@ -906,32 +906,35 @@
static jint CameraMetadata_setupGlobalVendorTagDescriptor(JNIEnv *env, jobject thiz) {
const String16 NAME("media.camera");
- sp<ICameraService> cameraService;
+ sp<hardware::ICameraService> cameraService;
status_t err = getService(NAME, /*out*/&cameraService);
if (err != OK) {
ALOGE("%s: Failed to get camera service, received error %s (%d)", __FUNCTION__,
strerror(-err), err);
- return err;
+ return hardware::ICameraService::ERROR_DISCONNECTED;
}
- sp<VendorTagDescriptor> desc;
- err = cameraService->getCameraVendorTagDescriptor(/*out*/desc);
+ sp<VendorTagDescriptor> desc = new VendorTagDescriptor();
+ binder::Status res = cameraService->getCameraVendorTagDescriptor(/*out*/desc.get());
- if (err == -EOPNOTSUPP) {
- ALOGW("%s: Camera HAL too old; does not support vendor tags", __FUNCTION__);
+ if (res.serviceSpecificErrorCode() == hardware::ICameraService::ERROR_DISCONNECTED) {
+ // No camera module available, not an error on devices with no cameras
VendorTagDescriptor::clearGlobalVendorTagDescriptor();
-
return OK;
- } else if (err != OK) {
- ALOGE("%s: Failed to setup vendor tag descriptors, received error %s (%d)",
- __FUNCTION__, strerror(-err), err);
- return err;
+ } else if (!res.isOk()) {
+ VendorTagDescriptor::clearGlobalVendorTagDescriptor();
+ ALOGE("%s: Failed to setup vendor tag descriptors: %s",
+ __FUNCTION__, res.toString8().string());
+ return res.serviceSpecificErrorCode();
}
err = VendorTagDescriptor::setAsGlobalVendorTagDescriptor(desc);
- return err;
+ if (err != OK) {
+ return hardware::ICameraService::ERROR_INVALID_OPERATION;
+ }
+ return OK;
}
} // extern "C"
diff --git a/core/jni/android_net_NetUtils.cpp b/core/jni/android_net_NetUtils.cpp
index defb88a..880a79c 100644
--- a/core/jni/android_net_NetUtils.cpp
+++ b/core/jni/android_net_NetUtils.cpp
@@ -26,10 +26,13 @@
#include <net/if.h>
#include <linux/filter.h>
#include <linux/if.h>
+#include <linux/if_arp.h>
#include <linux/if_ether.h>
#include <linux/if_packet.h>
#include <net/if_ether.h>
+#include <netinet/icmp6.h>
#include <netinet/ip.h>
+#include <netinet/ip6.h>
#include <netinet/udp.h>
#include <cutils/properties.h>
@@ -64,10 +67,9 @@
static void android_net_utils_attachDhcpFilter(JNIEnv *env, jobject clazz, jobject javaFd)
{
- int fd = jniGetFDFromFileDescriptor(env, javaFd);
uint32_t ip_offset = sizeof(ether_header);
uint32_t proto_offset = ip_offset + offsetof(iphdr, protocol);
- uint32_t flags_offset = ip_offset + offsetof(iphdr, frag_off);
+ uint32_t flags_offset = ip_offset + offsetof(iphdr, frag_off);
uint32_t dport_indirect_offset = ip_offset + offsetof(udphdr, dest);
struct sock_filter filter_code[] = {
// Check the protocol is UDP.
@@ -94,6 +96,45 @@
filter_code,
};
+ int fd = jniGetFDFromFileDescriptor(env, javaFd);
+ if (setsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER, &filter, sizeof(filter)) != 0) {
+ jniThrowExceptionFmt(env, "java/net/SocketException",
+ "setsockopt(SO_ATTACH_FILTER): %s", strerror(errno));
+ }
+}
+
+static void android_net_utils_attachRaFilter(JNIEnv *env, jobject clazz, jobject javaFd,
+ jint hardwareAddressType)
+{
+ if (hardwareAddressType != ARPHRD_ETHER) {
+ jniThrowExceptionFmt(env, "java/net/SocketException",
+ "attachRaFilter only supports ARPHRD_ETHER");
+ return;
+ }
+
+ uint32_t ipv6_offset = sizeof(ether_header);
+ uint32_t ipv6_next_header_offset = ipv6_offset + offsetof(ip6_hdr, ip6_nxt);
+ uint32_t icmp6_offset = ipv6_offset + sizeof(ip6_hdr);
+ uint32_t icmp6_type_offset = icmp6_offset + offsetof(icmp6_hdr, icmp6_type);
+ struct sock_filter filter_code[] = {
+ // Check IPv6 Next Header is ICMPv6.
+ BPF_STMT(BPF_LD | BPF_B | BPF_ABS, ipv6_next_header_offset),
+ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, IPPROTO_ICMPV6, 0, 3),
+
+ // Check ICMPv6 type is Router Advertisement.
+ BPF_STMT(BPF_LD | BPF_B | BPF_ABS, icmp6_type_offset),
+ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, ND_ROUTER_ADVERT, 0, 1),
+
+ // Accept or reject.
+ BPF_STMT(BPF_RET | BPF_K, 0xffff),
+ BPF_STMT(BPF_RET | BPF_K, 0)
+ };
+ struct sock_fprog filter = {
+ sizeof(filter_code) / sizeof(filter_code[0]),
+ filter_code,
+ };
+
+ int fd = jniGetFDFromFileDescriptor(env, javaFd);
if (setsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER, &filter, sizeof(filter)) != 0) {
jniThrowExceptionFmt(env, "java/net/SocketException",
"setsockopt(SO_ATTACH_FILTER): %s", strerror(errno));
@@ -148,6 +189,7 @@
{ "protectFromVpn", "(I)Z", (void*)android_net_utils_protectFromVpn },
{ "queryUserAccess", "(II)Z", (void*)android_net_utils_queryUserAccess },
{ "attachDhcpFilter", "(Ljava/io/FileDescriptor;)V", (void*) android_net_utils_attachDhcpFilter },
+ { "attachRaFilter", "(Ljava/io/FileDescriptor;I)V", (void*) android_net_utils_attachRaFilter },
};
int register_android_net_NetworkUtils(JNIEnv* env)
diff --git a/core/jni/android_os_Debug.cpp b/core/jni/android_os_Debug.cpp
index 3df0876..f870a89 100644
--- a/core/jni/android_os_Debug.cpp
+++ b/core/jni/android_os_Debug.cpp
@@ -262,7 +262,13 @@
}
name = line + name_pos;
nameLen = strlen(name);
-
+ // Trim the end of the line if it is " (deleted)".
+ const char* deleted_str = " (deleted)";
+ if (nameLen > (int)strlen(deleted_str) &&
+ strcmp(name+nameLen-strlen(deleted_str), deleted_str) == 0) {
+ nameLen -= strlen(deleted_str);
+ name[nameLen] = '\0';
+ }
if ((strstr(name, "[heap]") == name)) {
whichHeap = HEAP_NATIVE;
} else if (strncmp(name, "[anon:libc_malloc]", 18) == 0) {
diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp
index cf68449..b7701d6 100644
--- a/core/jni/android_view_Surface.cpp
+++ b/core/jni/android_view_Surface.cpp
@@ -411,22 +411,27 @@
return 0;
}
+ android::view::Surface surfaceShim;
+
+ // Calling code in Surface.java has already read the name of the Surface
+ // from the Parcel
+ surfaceShim.readFromParcel(parcel, /*nameAlreadyRead*/true);
+
sp<Surface> self(reinterpret_cast<Surface *>(nativeObject));
- sp<IBinder> binder(parcel->readStrongBinder());
// update the Surface only if the underlying IGraphicBufferProducer
// has changed.
- if (self != NULL
- && (IInterface::asBinder(self->getIGraphicBufferProducer()) == binder)) {
+ if (self != nullptr
+ && (IInterface::asBinder(self->getIGraphicBufferProducer()) ==
+ IInterface::asBinder(surfaceShim.graphicBufferProducer))) {
// same IGraphicBufferProducer, return ourselves
return jlong(self.get());
}
sp<Surface> sur;
- sp<IGraphicBufferProducer> gbp(interface_cast<IGraphicBufferProducer>(binder));
- if (gbp != NULL) {
+ if (surfaceShim.graphicBufferProducer != nullptr) {
// we have a new IGraphicBufferProducer, create a new Surface for it
- sur = new Surface(gbp, true);
+ sur = new Surface(surfaceShim.graphicBufferProducer, true);
// and keep a reference before passing to java
sur->incStrong(&sRefBaseOwner);
}
@@ -447,7 +452,13 @@
return;
}
sp<Surface> self(reinterpret_cast<Surface *>(nativeObject));
- parcel->writeStrongBinder( self != 0 ? IInterface::asBinder(self->getIGraphicBufferProducer()) : NULL);
+ android::view::Surface surfaceShim;
+ if (self != nullptr) {
+ surfaceShim.graphicBufferProducer = self->getIGraphicBufferProducer();
+ }
+ // Calling code in Surface.java has already written the name of the Surface
+ // to the Parcel
+ surfaceShim.writeToParcel(parcel, /*nameAlreadyWritten*/true);
}
static jint nativeGetWidth(JNIEnv* env, jclass clazz, jlong nativeObject) {
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index 1dfe40a..c838d03 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -110,6 +110,13 @@
ctrl->decStrong((void *)nativeCreate);
}
+static void nativeDisconnect(JNIEnv* env, jclass clazz, jlong nativeObject) {
+ SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
+ if (ctrl != NULL) {
+ ctrl->disconnect();
+ }
+}
+
static jobject nativeScreenshotBitmap(JNIEnv* env, jclass clazz,
jobject displayTokenObj, jobject sourceCropObj, jint width, jint height,
jint minLayer, jint maxLayer, bool allLayers, bool useIdentityTransform,
@@ -595,6 +602,8 @@
(void*)nativeRelease },
{"nativeDestroy", "(J)V",
(void*)nativeDestroy },
+ {"nativeDisconnect", "(J)V",
+ (void*)nativeDisconnect },
{"nativeScreenshot", "(Landroid/os/IBinder;Landroid/graphics/Rect;IIIIZZI)Landroid/graphics/Bitmap;",
(void*)nativeScreenshotBitmap },
{"nativeScreenshot", "(Landroid/os/IBinder;Landroid/view/Surface;Landroid/graphics/Rect;IIIIZZ)V",
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 588e738..8f85d4a 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -87,6 +87,7 @@
<protected-broadcast android:name="android.os.action.DEVICE_IDLE_MODE_CHANGED" />
<protected-broadcast android:name="android.os.action.POWER_SAVE_WHITELIST_CHANGED" />
<protected-broadcast android:name="android.os.action.POWER_SAVE_TEMP_WHITELIST_CHANGED" />
+ <protected-broadcast android:name="android.os.action.POWER_SAVE_MODE_CHANGED_INTERNAL" />
<protected-broadcast android:name="android.os.action.SCREEN_BRIGHTNESS_BOOST_CHANGED" />
@@ -265,6 +266,7 @@
<protected-broadcast android:name="com.android.server.WifiManager.action.START_SCAN" />
<protected-broadcast android:name="com.android.server.WifiManager.action.START_PNO" />
<protected-broadcast android:name="com.android.server.WifiManager.action.DELAYED_DRIVER_STOP" />
+ <protected-broadcast android:name="com.android.server.WifiManager.action.DEVICE_IDLE" />
<protected-broadcast android:name="com.android.server.action.REMOTE_BUGREPORT_SHARING_ACCEPTED" />
<protected-broadcast android:name="com.android.server.action.REMOTE_BUGREPORT_SHARING_DECLINED" />
<protected-broadcast android:name="android.net.wifi.WIFI_STATE_CHANGED" />
@@ -374,7 +376,10 @@
<protected-broadcast android:name="android.app.action.ACTION_PASSWORD_FAILED" />
<protected-broadcast android:name="android.app.action.ACTION_PASSWORD_SUCCEEDED" />
<protected-broadcast android:name="com.android.server.ACTION_EXPIRED_PASSWORD_NOTIFICATION" />
+
<protected-broadcast android:name="android.intent.action.MANAGED_PROFILE_ADDED" />
+ <protected-broadcast android:name="android.intent.action.MANAGED_PROFILE_UNLOCKED" />
+ <protected-broadcast android:name="android.intent.action.MANAGED_PROFILE_REMOVED" />
<protected-broadcast android:name="android.bluetooth.adapter.action.BLE_STATE_CHANGED" />
<protected-broadcast android:name="android.content.jobscheduler.JOB_DELAY_EXPIRED" />
@@ -432,7 +437,6 @@
<protected-broadcast android:name="android.intent.action.DYNAMIC_SENSOR_CHANGED" />
<protected-broadcast android:name="android.intent.action.ACTION_RADIO_OFF" />
- <protected-broadcast android:name="android.intent.action.MANAGED_PROFILE_UNLOCKED" />
<protected-broadcast android:name="android.accounts.LOGIN_ACCOUNTS_CHANGED" />
<protected-broadcast android:name="com.android.sync.SYNC_CONN_STATUS_CHANGED" />
@@ -450,6 +454,10 @@
<protected-broadcast android:name="android.intent.action.TWILIGHT_CHANGED" />
+ <protected-broadcast android:name="com.android.server.fingerprint.ACTION_LOCKOUT_RESET" />
+ <protected-broadcast android:name="android.net.wifi.PASSPOINT_ICON_RECEIVED" />
+ <protected-broadcast android:name="com.android.server.notification.CountdownConditionProvider" />
+
<!-- ====================================================================== -->
<!-- RUNTIME PERMISSIONS -->
<!-- ====================================================================== -->
diff --git a/core/res/res/drawable-nodpi/default_wallpaper.jpg b/core/res/res/drawable-nodpi/default_wallpaper.jpg
deleted file mode 100644
index d7475b4c..0000000
--- a/core/res/res/drawable-nodpi/default_wallpaper.jpg
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-nodpi/default_wallpaper.png b/core/res/res/drawable-nodpi/default_wallpaper.png
new file mode 100644
index 0000000..e9c4d5c
--- /dev/null
+++ b/core/res/res/drawable-nodpi/default_wallpaper.png
Binary files differ
diff --git a/core/res/res/drawable-sw600dp-nodpi/default_wallpaper.jpg b/core/res/res/drawable-sw600dp-nodpi/default_wallpaper.jpg
deleted file mode 100644
index 03a14c0..0000000
--- a/core/res/res/drawable-sw600dp-nodpi/default_wallpaper.jpg
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-sw600dp-nodpi/default_wallpaper.png b/core/res/res/drawable-sw600dp-nodpi/default_wallpaper.png
new file mode 100644
index 0000000..9f3efa5
--- /dev/null
+++ b/core/res/res/drawable-sw600dp-nodpi/default_wallpaper.png
Binary files differ
diff --git a/core/res/res/drawable-sw720dp-nodpi/default_wallpaper.jpg b/core/res/res/drawable-sw720dp-nodpi/default_wallpaper.jpg
deleted file mode 100644
index 543d118..0000000
--- a/core/res/res/drawable-sw720dp-nodpi/default_wallpaper.jpg
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-sw720dp-nodpi/default_wallpaper.png b/core/res/res/drawable-sw720dp-nodpi/default_wallpaper.png
new file mode 100644
index 0000000..8199e70
--- /dev/null
+++ b/core/res/res/drawable-sw720dp-nodpi/default_wallpaper.png
Binary files differ
diff --git a/core/res/res/drawable/work_widget_mask_view_background.xml b/core/res/res/drawable/work_widget_mask_view_background.xml
deleted file mode 100644
index 17f0dbc..0000000
--- a/core/res/res/drawable/work_widget_mask_view_background.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-Copyright (C) 2015 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.
--->
- <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
- <padding android:left="5dp" android:right="5dp" android:top="5dp" android:bottom="5dp"/>
- <stroke android:width="1dp" android:color="#CCCCCC" />
- </shape>
diff --git a/core/res/res/layout/notification_template_material_big_text.xml b/core/res/res/layout/notification_template_material_big_text.xml
index 9a4b28c..3c59b4e 100644
--- a/core/res/res/layout/notification_template_material_big_text.xml
+++ b/core/res/res/layout/notification_template_material_big_text.xml
@@ -39,7 +39,7 @@
<com.android.internal.widget.ImageFloatingTextView android:id="@+id/big_text"
android:layout_width="match_parent"
android:layout_height="0dp"
- android:layout_marginTop="1.5dp"
+ android:layout_marginTop="1dp"
android:paddingBottom="@dimen/notification_content_margin_bottom"
android:textAppearance="@style/TextAppearance.Material.Notification"
android:singleLine="false"
diff --git a/core/res/res/layout/notification_template_text.xml b/core/res/res/layout/notification_template_text.xml
index 38470cd..47b30ec 100644
--- a/core/res/res/layout/notification_template_text.xml
+++ b/core/res/res/layout/notification_template_text.xml
@@ -14,12 +14,12 @@
~ See the License for the specific language governing permissions and
~ limitations under the License
-->
-<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+<com.android.internal.widget.ImageFloatingTextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="top"
- android:layout_marginTop="1.5dp"
+ android:layout_marginTop="1dp"
android:ellipsize="marquee"
android:fadingEdge="horizontal"
android:gravity="top"
diff --git a/core/res/res/layout/work_widget_mask_view.xml b/core/res/res/layout/work_widget_mask_view.xml
index ce86ddc..3c47705 100644
--- a/core/res/res/layout/work_widget_mask_view.xml
+++ b/core/res/res/layout/work_widget_mask_view.xml
@@ -15,20 +15,24 @@
limitations under the License.
-->
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/work_widget_mask_frame"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:background="#F3374248" >
+ android:background="#F3374248"
+ android:clickable="true" >
<ImageView android:id="@+id/work_widget_app_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_gravity="center"/>
+ android:layout_gravity="center"
+ android:clickable="false" />
- <ImageView
+ <ImageView android:id="@+id/work_widget_badge_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|right"
android:layout_marginBottom="4dp"
android:layout_marginRight="4dp"
- android:src="@drawable/ic_corp_badge_off" />
+ android:src="@drawable/ic_corp_badge_off"
+ android:clickable="false" />
</FrameLayout>
diff --git a/core/res/res/values-b+sr+Latn/strings.xml b/core/res/res/values-b+sr+Latn/strings.xml
index 8c00151..7ed9a20 100644
--- a/core/res/res/values-b+sr+Latn/strings.xml
+++ b/core/res/res/values-b+sr+Latn/strings.xml
@@ -163,7 +163,7 @@
<string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"Previše <xliff:g id="CONTENT_TYPE">%s</xliff:g> izbrisanih stavki."</string>
<string name="low_memory" product="tablet" msgid="6494019234102154896">"Memorija tableta je puna! Izbrišite neke datoteke da biste oslobodili prostor."</string>
<string name="low_memory" product="watch" msgid="4415914910770005166">"Memorija sata je puna. Izbrišite neke datoteke da biste oslobodili prostor."</string>
- <string name="low_memory" product="tv" msgid="516619861191025923">"Skladišni prostor na TV-u je popunjen. Izbrišite neke datoteke da biste oslobodili prostor."</string>
+ <string name="low_memory" product="tv" msgid="516619861191025923">"Memorijski prostor na TV-u je popunjen. Izbrišite neke datoteke da biste oslobodili prostor."</string>
<string name="low_memory" product="default" msgid="3475999286680000541">"Skladište telefona je puno! Izbrišite neke datoteke kako biste oslobodili prostor."</string>
<string name="ssl_ca_cert_warning" msgid="5848402127455021714">"Mreža se možda nadgleda"</string>
<string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"Od strane nepoznate treće strane"</string>
@@ -312,7 +312,7 @@
<string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"Dozvoljava aplikaciji da učini sopstvene komponente trajnim u memoriji. Ovo može da ograniči memoriju dostupnu drugim aplikacijama i uspori tablet."</string>
<string name="permdesc_persistentActivity" product="tv" msgid="5086862529499103587">"Dozvoljava aplikaciji da neke svoje delove trajno zadrži u memoriji. To može da ograniči memoriju dostupnu drugim aplikacijama i uspori TV."</string>
<string name="permdesc_persistentActivity" product="default" msgid="4384760047508278272">"Dozvoljava aplikaciji da učini sopstvene komponente trajnim u memoriji. Ovo može da ograniči memoriju dostupnu drugim aplikacijama i uspori telefon."</string>
- <string name="permlab_getPackageSize" msgid="7472921768357981986">"merenje prostora za skladištenje u aplikaciji"</string>
+ <string name="permlab_getPackageSize" msgid="7472921768357981986">"merenje memorijskog prostora u aplikaciji"</string>
<string name="permdesc_getPackageSize" msgid="3921068154420738296">"Dozvoljava aplikaciji da preuzme veličine kôda, podataka i keša."</string>
<string name="permlab_writeSettings" msgid="2226195290955224730">"izmena podešavanja sistema"</string>
<string name="permdesc_writeSettings" msgid="7775723441558907181">"Dozvoljava aplikaciji da menja podatke o podešavanju sistema. Zlonamerne aplikacije mogu da oštete konfiguraciju sistema."</string>
@@ -885,9 +885,9 @@
<string name="deleteText" msgid="6979668428458199034">"Izbriši"</string>
<string name="inputMethod" msgid="1653630062304567879">"Metod unosa"</string>
<string name="editTextMenuTitle" msgid="4909135564941815494">"Radnje u vezi sa tekstom"</string>
- <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Prostor za skladištenje je na izmaku"</string>
+ <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Memorijski prostor je na izmaku"</string>
<string name="low_internal_storage_view_text" msgid="6640505817617414371">"Neke sistemske funkcije možda ne funkcionišu"</string>
- <string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"Nema dovoljno skladišnog prostora za sistem. Uverite se da imate 250 MB slobodnog prostora i ponovo pokrenite."</string>
+ <string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"Nema dovoljno memorijskog prostora za sistem. Uverite se da imate 250 MB slobodnog prostora i ponovo pokrenite."</string>
<string name="app_running_notification_title" msgid="8718335121060787914">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> je pokrenuta"</string>
<string name="app_running_notification_text" msgid="4653586947747330058">"Dodirnite za više informacija ili zaustavljanje aplikacije."</string>
<string name="ok" msgid="5970060430562524910">"Potvrdi"</string>
diff --git a/core/res/res/values-eu-rES/strings.xml b/core/res/res/values-eu-rES/strings.xml
index 67776e7..2ed5463 100644
--- a/core/res/res/values-eu-rES/strings.xml
+++ b/core/res/res/values-eu-rES/strings.xml
@@ -1468,7 +1468,7 @@
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Eskatu desblokeatzeko eredua aingura kendu aurretik"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Eskatu pasahitza aingura kendu aurretik"</string>
<string name="dock_forced_resizable" msgid="5914261505436217520">"Baliteke aplikazioak ez funtzionatzea pantaila zatituan."</string>
- <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Aplikazioak ez du onartzen pantaila banatua"</string>
+ <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Aplikazioak ez du onartzen pantaila zatitua"</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"Administratzaileak instalatu du"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"Administratzaileak eguneratu du"</string>
<string name="package_deleted_device_owner" msgid="7650577387493101353">"Administratzaileak ezabatu du"</string>
@@ -1541,7 +1541,7 @@
<string name="importance_from_person" msgid="9160133597262938296">"Garrantzitsua da eragiten dien pertsonengatik."</string>
<string name="user_creation_account_exists" msgid="1942606193570143289">"<xliff:g id="APP">%1$s</xliff:g> aplikazioari <xliff:g id="ACCOUNT">%2$s</xliff:g> kontua duen erabiltzailea sortzea baimendu nahi diozu?"</string>
<string name="user_creation_adding" msgid="4482658054622099197">"<xliff:g id="APP">%1$s</xliff:g> aplikazioari <xliff:g id="ACCOUNT">%2$s</xliff:g> kontua duen erabiltzailea sortzea baimendu nahi diozu? (Badago kontu hori duen erabiltzaile bat)"</string>
- <string name="language_selection_title" msgid="2680677278159281088">"Gehitu hizkuntza bat"</string>
+ <string name="language_selection_title" msgid="2680677278159281088">"Gehitu hizkuntza"</string>
<string name="country_selection_title" msgid="2954859441620215513">"Lurralde-hobespena"</string>
<string name="search_language_hint" msgid="7042102592055108574">"Adierazi hizkuntza"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"Iradokitakoak"</string>
diff --git a/core/res/res/values-h426dp-port/integers.xml b/core/res/res/values-h426dp-port/integers.xml
new file mode 100644
index 0000000..94abbec
--- /dev/null
+++ b/core/res/res/values-h426dp-port/integers.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 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.
+*/
+-->
+<resources>
+ <integer name="date_picker_mode">2</integer>
+ <integer name="time_picker_mode">2</integer>
+</resources>
diff --git a/core/res/res/values-ky-rKG/strings.xml b/core/res/res/values-ky-rKG/strings.xml
index 018e054..a6ee770 100644
--- a/core/res/res/values-ky-rKG/strings.xml
+++ b/core/res/res/values-ky-rKG/strings.xml
@@ -1468,7 +1468,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Бошотуудан мурун PIN суралсын"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Бошотуудан мурун кулпуну ачкан үлгү суралсын"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Бошотуудан мурун сырсөз суралсын"</string>
- <string name="dock_forced_resizable" msgid="5914261505436217520">"Колдонмо бөлүнгөн экранда иштебей калышы мүмкүн."</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"Колдонмодо экран бөлүнбөшү мүмкүн."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Колдонмодо экран бөлүнбөйт."</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"Администраторуңуз тарабынан орнотулган"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"Администраторуңуз жаңырткан"</string>
@@ -1542,7 +1542,7 @@
<string name="importance_from_person" msgid="9160133597262938296">"Булар сиз үчүн маанилүү адамдар."</string>
<string name="user_creation_account_exists" msgid="1942606193570143289">"<xliff:g id="APP">%1$s</xliff:g> колдонмосу <xliff:g id="ACCOUNT">%2$s</xliff:g> каттоо эсеби менен жаңы колдонуучу түзө берсинби ?"</string>
<string name="user_creation_adding" msgid="4482658054622099197">"<xliff:g id="APP">%1$s</xliff:g> колдонмосу <xliff:g id="ACCOUNT">%2$s</xliff:g> каттоо эсеби менен жаңы колдонуучу түзө берсинби (мындай каттоо эсеби бар колдонуучу мурунтан эле бар) ?"</string>
- <string name="language_selection_title" msgid="2680677278159281088">"Тилди кошуңуз"</string>
+ <string name="language_selection_title" msgid="2680677278159281088">"Тил кошуңуз"</string>
<string name="country_selection_title" msgid="2954859441620215513">"Чөлкөмдүк жөндөөлөр"</string>
<string name="search_language_hint" msgid="7042102592055108574">"Тилди киргизиңиз"</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"Сунушталган"</string>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index 8604e62..ecf45b7 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -1579,7 +1579,7 @@
<string name="importance_from_person" msgid="9160133597262938296">"Tai svarbu dėl susijusių žmonių."</string>
<string name="user_creation_account_exists" msgid="1942606193570143289">"Leisti „<xliff:g id="APP">%1$s</xliff:g>“ kurti naują <xliff:g id="ACCOUNT">%2$s</xliff:g> naudotoją?"</string>
<string name="user_creation_adding" msgid="4482658054622099197">"Leisti „<xliff:g id="APP">%1$s</xliff:g>“ kurti naują <xliff:g id="ACCOUNT">%2$s</xliff:g> naudotoją (šią paskyrą naudojantis naudotojas jau yra)?"</string>
- <string name="language_selection_title" msgid="2680677278159281088">"Kalbos pridėjimas"</string>
+ <string name="language_selection_title" msgid="2680677278159281088">"Pridėkite kalbą"</string>
<string name="country_selection_title" msgid="2954859441620215513">"Regiono nuostata"</string>
<string name="search_language_hint" msgid="7042102592055108574">"Įveskite kalbos pav."</string>
<string name="language_picker_section_suggested" msgid="8414489646861640885">"Siūloma"</string>
diff --git a/core/res/res/values-ms-rMY/strings.xml b/core/res/res/values-ms-rMY/strings.xml
index 06401bf..cd31b2b 100644
--- a/core/res/res/values-ms-rMY/strings.xml
+++ b/core/res/res/values-ms-rMY/strings.xml
@@ -1467,7 +1467,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"Minta PIN sebelum menyahsemat"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"Minta corak buka kunci sebelum menyahsemat"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"Minta kata laluan sebelum menyahsemat"</string>
- <string name="dock_forced_resizable" msgid="5914261505436217520">"Apl mungkin tidak berfungsi dengan skrin terpisah."</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"Apl mungkin tidak berfungsi dengan skrin pisah."</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Apl tidak menyokong skrin pisah."</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"Dipasang oleh pentadbir anda"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"Dikemas kini oleh pentadbir anda"</string>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index d1ac852..1e3a886 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -163,7 +163,7 @@
<string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"Превише <xliff:g id="CONTENT_TYPE">%s</xliff:g> избрисаних ставки."</string>
<string name="low_memory" product="tablet" msgid="6494019234102154896">"Меморија таблета је пуна! Избришите неке датотеке да бисте ослободили простор."</string>
<string name="low_memory" product="watch" msgid="4415914910770005166">"Меморија сата је пуна. Избришите неке датотеке да бисте ослободили простор."</string>
- <string name="low_memory" product="tv" msgid="516619861191025923">"Складишни простор на ТВ-у је попуњен. Избришите неке датотеке да бисте ослободили простор."</string>
+ <string name="low_memory" product="tv" msgid="516619861191025923">"Меморијски простор на ТВ-у је попуњен. Избришите неке датотеке да бисте ослободили простор."</string>
<string name="low_memory" product="default" msgid="3475999286680000541">"Складиште телефона је пуно! Избришите неке датотеке како бисте ослободили простор."</string>
<string name="ssl_ca_cert_warning" msgid="5848402127455021714">"Мрежа се можда надгледа"</string>
<string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"Од стране непознате треће стране"</string>
@@ -312,7 +312,7 @@
<string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"Дозвољава апликацији да учини сопствене компоненте трајним у меморији. Ово може да ограничи меморију доступну другим апликацијама и успори таблет."</string>
<string name="permdesc_persistentActivity" product="tv" msgid="5086862529499103587">"Дозвољава апликацији да неке своје делове трајно задржи у меморији. То може да ограничи меморију доступну другим апликацијама и успори ТВ."</string>
<string name="permdesc_persistentActivity" product="default" msgid="4384760047508278272">"Дозвољава апликацији да учини сопствене компоненте трајним у меморији. Ово може да ограничи меморију доступну другим апликацијама и успори телефон."</string>
- <string name="permlab_getPackageSize" msgid="7472921768357981986">"мерење простора за складиштење у апликацији"</string>
+ <string name="permlab_getPackageSize" msgid="7472921768357981986">"мерење меморијског простора у апликацији"</string>
<string name="permdesc_getPackageSize" msgid="3921068154420738296">"Дозвољава апликацији да преузме величине кôда, података и кеша."</string>
<string name="permlab_writeSettings" msgid="2226195290955224730">"измена подешавања система"</string>
<string name="permdesc_writeSettings" msgid="7775723441558907181">"Дозвољава апликацији да мења податке о подешавању система. Злонамерне апликације могу да оштете конфигурацију система."</string>
@@ -885,9 +885,9 @@
<string name="deleteText" msgid="6979668428458199034">"Избриши"</string>
<string name="inputMethod" msgid="1653630062304567879">"Метод уноса"</string>
<string name="editTextMenuTitle" msgid="4909135564941815494">"Радње у вези са текстом"</string>
- <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Простор за складиштење је на измаку"</string>
+ <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Меморијски простор је на измаку"</string>
<string name="low_internal_storage_view_text" msgid="6640505817617414371">"Неке системске функције можда не функционишу"</string>
- <string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"Нема довољно складишног простора за систем. Уверите се да имате 250 MB слободног простора и поново покрените."</string>
+ <string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"Нема довољно меморијског простора за систем. Уверите се да имате 250 MB слободног простора и поново покрените."</string>
<string name="app_running_notification_title" msgid="8718335121060787914">"Апликација <xliff:g id="APP_NAME">%1$s</xliff:g> је покренута"</string>
<string name="app_running_notification_text" msgid="4653586947747330058">"Додирните за више информација или заустављање апликације."</string>
<string name="ok" msgid="5970060430562524910">"Потврди"</string>
diff --git a/core/res/res/values-w426dp-land/integers.xml b/core/res/res/values-w426dp-land/integers.xml
new file mode 100644
index 0000000..94abbec
--- /dev/null
+++ b/core/res/res/values-w426dp-land/integers.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 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.
+*/
+-->
+<resources>
+ <integer name="date_picker_mode">2</integer>
+ <integer name="time_picker_mode">2</integer>
+</resources>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index 85616b1..24a5b79 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -1467,7 +1467,7 @@
<string name="lock_to_app_unlock_pin" msgid="2552556656504331634">"取消时要求输入PIN码"</string>
<string name="lock_to_app_unlock_pattern" msgid="4182192144797225137">"取消时要求绘制解锁图案"</string>
<string name="lock_to_app_unlock_password" msgid="6380979775916974414">"取消时要求输入密码"</string>
- <string name="dock_forced_resizable" msgid="5914261505436217520">"应用可能无法在分屏模式下运行。"</string>
+ <string name="dock_forced_resizable" msgid="5914261505436217520">"应用可能无法在分屏模式下正常运行。"</string>
<string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"应用不支持分屏。"</string>
<string name="package_installed_device_owner" msgid="8420696545959087545">"已由管理员安装"</string>
<string name="package_updated_device_owner" msgid="8856631322440187071">"由您单位的管理员更新"</string>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index b65f19b..9a2a6eb 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -443,6 +443,9 @@
<!-- Boolean indicating whether or not wifi firmware debugging is enabled -->
<bool translatable="false" name="config_wifi_enable_wifi_firmware_debugging">true</bool>
+ <!-- Integer size limit, in KB, for a single WifiLogger ringbuffer -->
+ <integer translatable="false" name="config_wifi_logger_ring_buffer_size_limit_kb">32</integer>
+
<!-- Boolean indicating whether or not wifi should turn off when emergency call is made -->
<bool translatable="false" name="config_wifi_turn_off_during_emergency_call">false</bool>
@@ -2479,4 +2482,8 @@
handle wallpaper cropping.
-->
<string name="config_wallpaperCropperPackage" translatable="false">com.android.wallpapercropper</string>
+
+ <!-- True if the device supports at least one form of multi-window.
+ E.g. freeform, split-screen, picture-in-picture. -->
+ <bool name="config_supportsMultiWindow">true</bool>
</resources>
diff --git a/core/res/res/values/integers.xml b/core/res/res/values/integers.xml
index 8e27226..8f8d59e 100644
--- a/core/res/res/values/integers.xml
+++ b/core/res/res/values/integers.xml
@@ -23,4 +23,7 @@
<integer name="button_pressed_animation_delay">100</integer>
<integer name="disabled_alpha_animation_duration">100</integer>
<integer name="dock_enter_exit_duration">250</integer>
+
+ <integer name="date_picker_mode">1</integer>
+ <integer name="time_picker_mode">1</integer>
</resources>
diff --git a/core/res/res/values/styles_material.xml b/core/res/res/values/styles_material.xml
index db418f7..a9c8a06 100644
--- a/core/res/res/values/styles_material.xml
+++ b/core/res/res/values/styles_material.xml
@@ -652,7 +652,7 @@
</style>
<style name="Widget.Material.TimePicker">
- <item name="timePickerMode">clock</item>
+ <item name="timePickerMode">@integer/time_picker_mode</item>
<item name="legacyLayout">@layout/time_picker_legacy_material</item>
<!-- Attributes for new-style TimePicker. -->
<item name="internalLayout">@layout/time_picker_material</item>
@@ -666,7 +666,7 @@
</style>
<style name="Widget.Material.DatePicker">
- <item name="datePickerMode">calendar</item>
+ <item name="datePickerMode">@integer/date_picker_mode</item>
<item name="legacyLayout">@layout/date_picker_legacy_holo</item>
<item name="calendarViewShown">true</item>
<!-- Attributes for new-style DatePicker. -->
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 44a7a8d..11f42ec 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -298,11 +298,13 @@
<java-symbol type="bool" name="config_wifi_enable_5GHz_preference" />
<java-symbol type="bool" name="config_wifi_revert_country_code_on_cellular_loss" />
<java-symbol type="bool" name="config_wifi_enable_wifi_firmware_debugging" />
+ <java-symbol type="integer" name="config_wifi_logger_ring_buffer_size_limit_kb" />
<java-symbol type="bool" name="config_wifi_turn_off_during_emergency_call" />
<java-symbol type="bool" name="config_supportMicNearUltrasound" />
<java-symbol type="bool" name="config_supportSpeakerNearUltrasound" />
<java-symbol type="bool" name="config_supportAudioSourceUnprocessed" />
<java-symbol type="bool" name="config_freeformWindowManagement" />
+ <java-symbol type="bool" name="config_supportsMultiWindow" />
<java-symbol type="bool" name="config_guestUserEphemeral" />
<java-symbol type="string" name="config_defaultPictureInPictureBounds" />
<java-symbol type="string" name="config_centeredPictureInPictureBounds" />
@@ -2431,8 +2433,9 @@
<java-symbol type="string" name="importance_from_person" />
<java-symbol type="layout" name="work_widget_mask_view" />
+ <java-symbol type="id" name="work_widget_mask_frame" />
<java-symbol type="id" name="work_widget_app_icon" />
- <java-symbol type="drawable" name="work_widget_mask_view_background" />
+ <java-symbol type="id" name="work_widget_badge_icon" />
<java-symbol type="id" name="aerr_report" />
<java-symbol type="id" name="aerr_reset" />
diff --git a/core/res/res/values/themes_micro.xml b/core/res/res/values/themes_micro.xml
index 8bf635e..478d66c 100644
--- a/core/res/res/values/themes_micro.xml
+++ b/core/res/res/values/themes_micro.xml
@@ -24,7 +24,6 @@
<item name="windowBackground">@color/black</item>
<item name="windowContentOverlay">@null</item>
<item name="windowIsFloating">false</item>
- <item name="windowSwipeToDismiss">true</item>
<!-- Required to force windowInsets dispatch through application UI. -->
<item name="windowOverscan">true</item>
</style>
@@ -42,7 +41,6 @@
<item name="windowBackground">@color/white</item>
<item name="windowContentOverlay">@null</item>
<item name="windowIsFloating">false</item>
- <item name="windowSwipeToDismiss">true</item>
<!-- Required to force windowInsets dispatch through application UI. -->
<item name="windowOverscan">true</item>
</style>
diff --git a/core/tests/coretests/src/android/animation/ValueAnimatorTests.java b/core/tests/coretests/src/android/animation/ValueAnimatorTests.java
index 998c72a..c92863d 100644
--- a/core/tests/coretests/src/android/animation/ValueAnimatorTests.java
+++ b/core/tests/coretests/src/android/animation/ValueAnimatorTests.java
@@ -328,7 +328,12 @@
// Only a1's pause listener should be called.
assertTrue(l1.pauseCalled);
assertFalse(l1.resumeCalled);
- a1.resume();
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ a1.resume();
+ }
+ });
Thread.sleep(a1.getTotalDuration());
diff --git a/core/tests/coretests/src/android/content/res/ConfigurationBoundResourceCacheTest.java b/core/tests/coretests/src/android/content/res/ConfigurationBoundResourceCacheTest.java
index e9fd5fb..5d46489 100644
--- a/core/tests/coretests/src/android/content/res/ConfigurationBoundResourceCacheTest.java
+++ b/core/tests/coretests/src/android/content/res/ConfigurationBoundResourceCacheTest.java
@@ -38,7 +38,7 @@
@Override
protected void setUp() throws Exception {
super.setUp();
- mCache = new ConfigurationBoundResourceCache<Float>(getActivity().getResources());
+ mCache = new ConfigurationBoundResourceCache<>();
}
public void testGetEmpty() {
diff --git a/core/tests/coretests/src/android/text/method/ForwardDeleteTest.java b/core/tests/coretests/src/android/text/method/ForwardDeleteTest.java
new file mode 100644
index 0000000..da17045
--- /dev/null
+++ b/core/tests/coretests/src/android/text/method/ForwardDeleteTest.java
@@ -0,0 +1,472 @@
+/*
+ * 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.
+ */
+
+package android.text.method;
+
+import android.app.Activity;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.test.suitebuilder.annotation.Suppress;
+import android.text.InputType;
+import android.text.method.BaseKeyListener;
+import android.text.method.KeyListenerTestCase;
+import android.view.KeyEvent;
+import android.widget.EditText;
+import android.widget.TextView.BufferType;
+
+/**
+ * Test forward delete key handling of {@link android.text.method.BaseKeyListener}.
+ *
+ * TODO: Move some of test cases to the CTS.
+ */
+public class ForwardDeleteTest extends KeyListenerTestCase {
+ private static final BaseKeyListener mKeyListener = new BaseKeyListener() {
+ public int getInputType() {
+ return InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_NORMAL;
+ }
+ };
+
+ // Sync the state to the TextView and call onKeyDown with KEYCODE_FORWARD_DEL key event.
+ // Then update the state to the result of TextView.
+ private void forwardDelete(final EditorState state, int modifiers) {
+ mActivity.runOnUiThread(new Runnable() {
+ public void run() {
+ mTextView.setText(state.mText, BufferType.EDITABLE);
+ mTextView.setKeyListener(mKeyListener);
+ mTextView.setSelection(state.mSelectionStart, state.mSelectionEnd);
+ }
+ });
+ mInstrumentation.waitForIdleSync();
+ assertTrue(mTextView.hasWindowFocus());
+
+ final KeyEvent keyEvent = getKey(KeyEvent.KEYCODE_FORWARD_DEL, modifiers);
+ mActivity.runOnUiThread(new Runnable() {
+ public void run() {
+ mTextView.onKeyDown(keyEvent.getKeyCode(), keyEvent);
+ }
+ });
+ mInstrumentation.waitForIdleSync();
+
+ state.mText = mTextView.getText();
+ state.mSelectionStart = mTextView.getSelectionStart();
+ state.mSelectionEnd = mTextView.getSelectionEnd();
+ }
+
+ @SmallTest
+ public void testSurrogatePairs() {
+ EditorState state = new EditorState();
+
+ // U+1F441 is EYE
+ state.setByString("| U+1F441");
+ forwardDelete(state, 0);
+ state.assertEquals("|");
+
+ // U+1F5E8 is LEFT SPEECH BUBBLE
+ state.setByString("| U+1F441 U+1F5E8");
+ forwardDelete(state, 0);
+ state.assertEquals("| U+1F5E8");
+ forwardDelete(state, 0);
+ state.assertEquals("|");
+
+ // TODO: introduce edge cases.
+ }
+
+ @SmallTest
+ public void testReplacementSpan() {
+ EditorState state = new EditorState();
+
+ state.setByString("| 'abc' ( 'de' ) 'fg'");
+ forwardDelete(state, 0);
+ state.assertEquals("| 'bc' ( 'de' ) 'fg'");
+ forwardDelete(state, 0);
+ state.assertEquals("| 'c' ( 'de' ) 'fg'");
+ forwardDelete(state, 0);
+ state.assertEquals("| ( 'de' ) 'fg'");
+ forwardDelete(state, 0);
+ state.assertEquals("| 'fg'");
+ forwardDelete(state, 0);
+ state.assertEquals("| 'g'");
+ forwardDelete(state, 0);
+ state.assertEquals("|");
+
+ state.setByString("'abc' [ ( 'de' ) ] 'fg'");
+ forwardDelete(state, 0);
+ state.assertEquals("'abc' | 'fg'");
+ forwardDelete(state, 0);
+ state.assertEquals("'abc' | 'g'");
+ forwardDelete(state, 0);
+ state.assertEquals("'abc' |");
+ forwardDelete(state, 0);
+ state.assertEquals("'abc' |");
+
+ state.setByString("'ab' [ 'c' ( 'de' ) 'f' ] 'g'");
+ forwardDelete(state, 0);
+ state.assertEquals("'ab' | 'g'");
+ forwardDelete(state, 0);
+ state.assertEquals("'ab' |");
+ forwardDelete(state, 0);
+ state.assertEquals("'ab' |");
+
+ // TODO: introduce edge cases.
+ }
+
+ @SmallTest
+ public void testCombiningEnclosingKeycaps() {
+ EditorState state = new EditorState();
+
+ // U+20E3 is COMBINING ENCLOSING KEYCAP.
+ state.setByString("| '1' U+20E3");
+ forwardDelete(state, 0);
+ state.assertEquals("|");
+
+ // Edge cases
+ // multiple COMBINING ENCLOSING KEYCAP
+ state.setByString("| '1' U+20E3 U+20E3");
+ forwardDelete(state, 0);
+ state.assertEquals("|");
+
+ // Isolated COMBINING ENCLOSING KEYCAP
+ state.setByString("| U+20E3");
+ forwardDelete(state, 0);
+ state.assertEquals("|");
+
+ // Isolated multiple COMBINING ENCLOSING KEYCAP
+ state.setByString("| U+20E3 U+20E3");
+ forwardDelete(state, 0);
+ state.assertEquals("|");
+ }
+
+ @SmallTest
+ public void testVariationSelector() {
+ EditorState state = new EditorState();
+
+ // U+FE0F is VARIATION SELECTOR-16.
+ state.setByString("| '#' U+FE0F");
+ forwardDelete(state, 0);
+ state.assertEquals("|");
+
+ // U+E0100 is VARIATION SELECTOR-17.
+ state.setByString("| U+845B U+E0100");
+ forwardDelete(state, 0);
+ state.assertEquals("|");
+
+ // Edge cases
+ // Isolated variation selectors
+ state.setByString("| U+FE0F");
+ forwardDelete(state, 0);
+ state.assertEquals("|");
+
+ state.setByString("| U+E0100");
+ forwardDelete(state, 0);
+ state.assertEquals("|");
+
+ // Isolated multiple variation selectors
+ state.setByString("| U+FE0F U+FE0F");
+ forwardDelete(state, 0);
+ state.assertEquals("|");
+
+ state.setByString("| U+FE0F U+E0100");
+ forwardDelete(state, 0);
+ state.assertEquals("|");
+
+ state.setByString("| U+E0100 U+FE0F");
+ forwardDelete(state, 0);
+ state.assertEquals("|");
+
+ state.setByString("| U+E0100 U+E0100");
+ forwardDelete(state, 0);
+ state.assertEquals("|");
+
+ // Multiple variation selectors
+ state.setByString("| '#' U+FE0F U+FE0F");
+ forwardDelete(state, 0);
+ state.assertEquals("|");
+
+ state.setByString("| '#' U+FE0F U+E0100");
+ forwardDelete(state, 0);
+ state.assertEquals("|");
+
+ state.setByString("| U+845B U+E0100 U+FE0F");
+ forwardDelete(state, 0);
+ state.assertEquals("|");
+
+ state.setByString("| U+845B U+E0100 U+E0100");
+ forwardDelete(state, 0);
+ state.assertEquals("|");
+ }
+
+ @SmallTest
+ public void testEmojiZeroWidthJoinerSequence() {
+ EditorState state = new EditorState();
+
+ // U+200D is ZERO WIDTH JOINER.
+ state.setByString("| U+1F441 U+200D U+1F5E8");
+ forwardDelete(state, 0);
+ state.assertEquals("|");
+
+ state.setByString("| U+1F468 U+200D U+2764 U+FE0F U+200D U+1F48B U+200D U+1F468");
+ forwardDelete(state, 0);
+ state.assertEquals("|");
+
+ // Edge cases
+ // End with ZERO WIDTH JOINER
+ state.setByString("| U+1F441 U+200D");
+ forwardDelete(state, 0);
+ state.assertEquals("|");
+
+ // Start with ZERO WIDTH JOINER
+ state.setByString("| U+200D U+1F5E8");
+ forwardDelete(state, 0);
+ state.assertEquals("| U+1F5E8");
+ forwardDelete(state, 0);
+ state.assertEquals("|");
+
+ // Multiple ZERO WIDTH JOINER
+ state.setByString("| U+1F441 U+200D U+200D U+1F5E8");
+ forwardDelete(state, 0);
+ state.assertEquals("| U+1F5E8");
+ forwardDelete(state, 0);
+ state.assertEquals("|");
+
+ // Isolated ZERO WIDTH JOINER
+ state.setByString("| U+200D");
+ forwardDelete(state, 0);
+ state.assertEquals("|");
+
+ // Isolated multiple ZERO WIDTH JOINER
+ state.setByString("| U+200D U+200D");
+ forwardDelete(state, 0);
+ state.assertEquals("|");
+ }
+
+ @SmallTest
+ public void testFlags() {
+ EditorState state = new EditorState();
+
+ // U+1F1FA is REGIONAL INDICATOR SYMBOL LETTER U.
+ // U+1F1F8 is REGIONAL INDICATOR SYMBOL LETTER S.
+ state.setByString("| U+1F1FA U+1F1F8");
+ forwardDelete(state, 0);
+ state.assertEquals("|");
+
+ state.setByString("| U+1F1FA U+1F1F8 U+1F1FA U+1F1F8");
+ forwardDelete(state, 0);
+ state.assertEquals("| U+1F1FA U+1F1F8");
+ forwardDelete(state, 0);
+ state.assertEquals("|");
+
+ // Edge cases
+ // Isolated regional indicator symbol
+ state.setByString("| U+1F1FA");
+ forwardDelete(state, 0);
+ state.assertEquals("|");
+
+ // Odd numbered regional indicator symbols
+ state.setByString("| U+1F1FA U+1F1F8 U+1F1FA");
+ forwardDelete(state, 0);
+ state.assertEquals("| U+1F1FA");
+ forwardDelete(state, 0);
+ state.assertEquals("|");
+ }
+
+ @SmallTest
+ public void testEmojiModifier() {
+ EditorState state = new EditorState();
+
+ // U+1F3FB is EMOJI MODIFIER FITZPATRICK TYPE-1-2.
+ state.setByString("| U+1F466 U+1F3FB");
+ forwardDelete(state, 0);
+ state.assertEquals("|");
+
+ // Edge cases
+ // Isolated emoji modifier
+ state.setByString("| U+1F3FB");
+ forwardDelete(state, 0);
+ state.assertEquals("|");
+
+ // Isolated multiple emoji modifier
+ state.setByString("| U+1F3FB U+1F3FB");
+ forwardDelete(state, 0);
+ state.assertEquals("| U+1F3FB");
+ forwardDelete(state, 0);
+ state.assertEquals("|");
+
+ // Multiple emoji modifiers
+ state.setByString("| U+1F466 U+1F3FB U+1F3FB");
+ forwardDelete(state, 0);
+ state.assertEquals("| U+1F3FB");
+ forwardDelete(state, 0);
+ state.assertEquals("|");
+ }
+
+ @SmallTest
+ public void testMixedEdgeCases() {
+ EditorState state = new EditorState();
+
+ // COMBINING ENCLOSING KEYCAP + variation selector
+ state.setByString("| '1' U+20E3 U+FE0F");
+ forwardDelete(state, 0);
+ state.assertEquals("|");
+
+ // Variation selector + COMBINING ENCLOSING KEYCAP
+ state.setByString("| U+2665 U+FE0F U+20E3");
+ forwardDelete(state, 0);
+ state.assertEquals("|");
+
+ // COMBINING ENCLOSING KEYCAP + ending with ZERO WIDTH JOINER
+ state.setByString("| '1' U+20E3 U+200D");
+ forwardDelete(state, 0);
+ state.assertEquals("|");
+
+ // COMBINING ENCLOSING KEYCAP + ZERO WIDTH JOINER
+ state.setByString("| '1' U+20E3 U+200D U+1F5E8");
+ forwardDelete(state, 0);
+ state.assertEquals("| U+1F5E8 ");
+
+ // Start with ZERO WIDTH JOINER + COMBINING ENCLOSING KEYCAP
+ state.setByString("| U+200D U+20E3");
+ forwardDelete(state, 0);
+ state.assertEquals("|");
+
+ // ZERO WIDTH JOINER + COMBINING ENCLOSING KEYCAP
+ state.setByString("| U+1F441 U+200D U+20E3");
+ forwardDelete(state, 0);
+ state.assertEquals("|");
+
+ // COMBINING ENCLOSING KEYCAP + regional indicator symbol
+ state.setByString("| '1' U+20E3 U+1F1FA");
+ forwardDelete(state, 0);
+ state.assertEquals("| U+1F1FA");
+ forwardDelete(state, 0);
+ state.assertEquals("|");
+
+ // Regional indicator symbol + COMBINING ENCLOSING KEYCAP
+ state.setByString("| U+1F1FA U+20E3");
+ forwardDelete(state, 0);
+ state.assertEquals("|");
+
+ // COMBINING ENCLOSING KEYCAP + emoji modifier
+ state.setByString("| '1' U+20E3 U+1F3FB");
+ forwardDelete(state, 0);
+ state.assertEquals("| U+1F3FB");
+
+ // Emoji modifier + COMBINING ENCLOSING KEYCAP
+ state.setByString("| U+1F466 U+1F3FB U+20E3");
+ forwardDelete(state, 0);
+ state.assertEquals("|");
+
+ // Variation selector + end with ZERO WIDTH JOINER
+ state.setByString("| U+2665 U+FE0F U+200D");
+ forwardDelete(state, 0);
+ state.assertEquals("|");
+
+ // Variation selector + ZERO WIDTH JOINER
+ state.setByString("| U+1F469 U+200D U+2764 U+FE0F U+200D U+1F469");
+ forwardDelete(state, 0);
+ state.assertEquals("|");
+
+ // Start with ZERO WIDTH JOINER + variation selector
+ state.setByString("| U+200D U+FE0F");
+ forwardDelete(state, 0);
+ state.assertEquals("|");
+
+ // ZERO WIDTH JOINER + variation selector
+ state.setByString("| U+1F469 U+200D U+FE0F");
+ forwardDelete(state, 0);
+ state.assertEquals("|");
+
+ // Variation selector + regional indicator symbol
+ state.setByString("| U+2665 U+FE0F U+1F1FA");
+ forwardDelete(state, 0);
+ state.assertEquals("| U+1F1FA");
+ forwardDelete(state, 0);
+ state.assertEquals("|");
+
+ // Regional indicator symbol + variation selector
+ state.setByString("| U+1F1FA U+FE0F");
+ forwardDelete(state, 0);
+ state.assertEquals("|");
+
+ // Variation selector + emoji modifier
+ state.setByString("| U+2665 U+FE0F U+1F3FB");
+ forwardDelete(state, 0);
+ state.assertEquals("| U+1F3FB");
+
+ // Emoji modifier + variation selector
+ state.setByString("| U+1F466 U+1F3FB U+FE0F");
+ forwardDelete(state, 0);
+ state.assertEquals("|");
+
+ // Start with ZERO WIDTH JOINER + regional indicator symbol
+ state.setByString("| U+200D U+1F1FA");
+ forwardDelete(state, 0);
+ state.assertEquals("| U+1F1FA");
+ forwardDelete(state, 0);
+ state.assertEquals("|");
+
+ // ZERO WIDTH JOINER + regional indicator symbol
+ state.setByString("| U+1F469 U+200D U+1F1FA");
+ forwardDelete(state, 0);
+ state.assertEquals("| U+1F1FA");
+
+ // Regional indicator symbol + end with ZERO WIDTH JOINER
+ state.setByString("| U+1F1FA U+200D");
+ forwardDelete(state, 0);
+ state.assertEquals("|");
+
+ // Regional indicator symbol + ZERO WIDTH JOINER
+ state.setByString("| U+1F1FA U+200D U+1F469");
+ forwardDelete(state, 0);
+ state.assertEquals("| U+1F469");
+ forwardDelete(state, 0);
+ state.assertEquals("|");
+
+ // Start with ZERO WIDTH JOINER + emoji modifier
+ state.setByString("| U+200D U+1F3FB");
+ forwardDelete(state, 0);
+ state.assertEquals("| U+1F3FB");
+
+ // ZERO WIDTH JOINER + emoji modifier
+ state.setByString("| U+1F469 U+200D U+1F3FB");
+ forwardDelete(state, 0);
+ state.assertEquals("| U+1F3FB");
+
+ // Emoji modifier + end with ZERO WIDTH JOINER
+ state.setByString("| U+1F466 U+1F3FB U+200D");
+ forwardDelete(state, 0);
+ state.assertEquals("|");
+
+ // Emoji modifier + ZERO WIDTH JOINER
+ state.setByString("| U+1F466 U+1F3FB U+200D U+1F469");
+ forwardDelete(state, 0);
+ state.assertEquals("| U+1F469");
+ forwardDelete(state, 0);
+ state.assertEquals("|");
+
+ // Regional indicator symbol + emoji modifier
+ state.setByString("| U+1F1FA U+1F3FB");
+ forwardDelete(state, 0);
+ state.assertEquals("| U+1F3FB");
+ forwardDelete(state, 0);
+ state.assertEquals("|");
+
+ // Emoji modifier + regional indicator symbol
+ state.setByString("| U+1F466 U+1F3FB U+1F1FA");
+ forwardDelete(state, 0);
+ state.assertEquals("| U+1F1FA");
+ forwardDelete(state, 0);
+ state.assertEquals("|");
+ }
+}
diff --git a/core/tests/coretests/src/android/util/PatternsTest.java b/core/tests/coretests/src/android/util/PatternsTest.java
index d383775..348f8fd 100644
--- a/core/tests/coretests/src/android/util/PatternsTest.java
+++ b/core/tests/coretests/src/android/util/PatternsTest.java
@@ -25,7 +25,7 @@
public class PatternsTest extends TestCase {
- //Tests for Patterns.TOP_LEVEL_DOMAIN
+ // Tests for Patterns.TOP_LEVEL_DOMAIN
@SmallTest
public void testTldPattern() throws Exception {
@@ -56,7 +56,7 @@
assertFalse("Matched invalid TLD!", t);
}
- //Tests for Patterns.IANA_TOP_LEVEL_DOMAINS
+ // Tests for Patterns.IANA_TOP_LEVEL_DOMAINS
@SmallTest
public void testIanaTopLevelDomains_matchesValidTld() throws Exception {
@@ -94,7 +94,7 @@
assertFalse("Should not match invalid Punycode TLD", pattern.matcher("xn").matches());
}
- //Tests for Patterns.WEB_URL
+ // Tests for Patterns.WEB_URL
@SmallTest
public void testWebUrl_matchesValidUrlWithSchemeAndHostname() throws Exception {
@@ -208,7 +208,7 @@
Patterns.WEB_URL.matcher(url).matches());
}
- //Tests for Patterns.AUTOLINK_WEB_URL
+ // Tests for Patterns.AUTOLINK_WEB_URL
@SmallTest
public void testAutoLinkWebUrl_matchesValidUrlWithSchemeAndHostname() throws Exception {
@@ -419,7 +419,7 @@
Patterns.AUTOLINK_WEB_URL.matcher(url).matches());
}
- //Tests for Patterns.IP_ADDRESS
+ // Tests for Patterns.IP_ADDRESS
@SmallTest
public void testIpPattern() throws Exception {
@@ -432,7 +432,7 @@
assertFalse("Invalid IP", t);
}
- //Tests for Patterns.DOMAIN_NAME
+ // Tests for Patterns.DOMAIN_NAME
@SmallTest
public void testDomain_matchesPunycodeTld() throws Exception {
@@ -508,7 +508,227 @@
Patterns.DOMAIN_NAME.matcher(domain).matches());
}
- //Tests for Patterns.PHONE
+ // Tests for Patterns.AUTOLINK_EMAIL_ADDRESS
+
+ public void testAutoLinkEmailAddress_matchesShortValidEmail() throws Exception {
+ String email = "a@a.co";
+ assertTrue("Should match short valid email: " + email,
+ Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+ }
+
+ public void testAutoLinkEmailAddress_matchesRegularEmail() throws Exception {
+ String email = "email@android.com";
+ assertTrue("Should match email: " + email,
+ Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+ }
+
+ public void testAutoLinkEmailAddress_matchesEmailWithMultipleSubdomains() throws Exception {
+ String email = "email@e.somelongdomainnameforandroid.abc.uk";
+ assertTrue("Should match email: " + email,
+ Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+ }
+
+ public void testAutoLinkEmailAddress_matchesLocalPartWithDot() throws Exception {
+ String email = "e.mail@android.com";
+ assertTrue("Should match email: " + email,
+ Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+ }
+
+ public void testAutoLinkEmailAddress_matchesLocalPartWithPlus() throws Exception {
+ String email = "e+mail@android.com";
+ assertTrue("Should match email: " + email,
+ Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+ }
+
+ public void testAutoLinkEmailAddress_matchesLocalPartWithUnderscore() throws Exception {
+ String email = "e_mail@android.com";
+ assertTrue("Should match email: " + email,
+ Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+ }
+
+ public void testAutoLinkEmailAddress_matchesLocalPartWithDash() throws Exception {
+ String email = "e-mail@android.com";
+ assertTrue("Should match email: " + email,
+ Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+ }
+
+ public void testAutoLinkEmailAddress_matchesLocalPartWithApostrophe() throws Exception {
+ String email = "e'mail@android.com";
+ assertTrue("Should match email: " + email,
+ Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+ }
+
+ public void testAutoLinkEmailAddress_matchesLocalPartWithDigits() throws Exception {
+ String email = "123@android.com";
+ assertTrue("Should match email: " + email,
+ Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+ }
+
+ public void testAutoLinkEmailAddress_matchesUnicodeLocalPart() throws Exception {
+ String email = "\uD604\uAE08\uC601\uC218\uC99D@android.kr";
+ assertTrue("Should match email: " + email,
+ Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+ }
+
+ public void testAutoLinkEmailAddress_matchesLocalPartWithEmoji() throws Exception {
+ String email = "smiley\u263A@android.com";
+ assertTrue("Should match email: " + email,
+ Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+ }
+
+ public void testAutoLinkEmailAddress_matchesLocalPartWithSurrogatePairs() throws Exception {
+ String email = "\uD83C\uDF38@android.com";
+ assertTrue("Should match email: " + email,
+ Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+ }
+
+ public void testAutoLinkEmailAddress_matchesDomainWithDash() throws Exception {
+ String email = "email@an-droid.com";
+ assertTrue("Should match email: " + email,
+ Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+ }
+
+ public void testAutoLinkEmailAddress_matchesUnicodeDomain() throws Exception {
+ String email = "email@\uD604\uAE08\uC601\uC218\uC99D.kr";
+ assertTrue("Should match email: " + email,
+ Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+ }
+
+ public void testAutoLinkEmailAddress_matchesUnicodeLocalPartAndDomain() throws Exception {
+ String email = "\uD604\uAE08\uC601\uC218\uC99D@\uD604\uAE08\uC601\uC218\uC99D.kr";
+ assertTrue("Should match email: " + email,
+ Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+ }
+
+ public void testAutoLinkEmailAddress_matchesDomainWithEmoji() throws Exception {
+ String email = "smiley@\u263Aandroid.com";
+ assertTrue("Should match email: " + email,
+ Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+ }
+
+ public void testAutoLinkEmailAddress_matchesDomainWithSurrogatePairs() throws Exception {
+ String email = "email@\uD83C\uDF38android.com";
+ assertTrue("Should match email: " + email,
+ Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+ }
+
+ public void testAutoLinkEmailAddress_matchesLocalPartAndDomainWithSurrogatePairs()
+ throws Exception {
+ String email = "\uD83C\uDF38@\uD83C\uDF38android.com";
+ assertTrue("Should match email: " + email,
+ Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+ }
+
+ public void testAutoLinkEmailAddress_doesNotMatchStringWithoutAtSign() throws Exception {
+ String email = "android.com";
+ assertFalse("Should not match email: " + email,
+ Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+ }
+
+ public void testAutoLinkEmailAddress_doesNotMatchPlainString() throws Exception {
+ String email = "email";
+ assertFalse("Should not match email: " + email,
+ Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+ }
+
+ public void testAutoLinkEmailAddress_doesNotMatchStringWithMultipleAtSigns() throws Exception {
+ String email = "email@android@android.com";
+ assertFalse("Should not match email: " + email,
+ Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+ }
+
+ public void testAutoLinkEmailAddress_doesNotMatchEmailWithoutTld() throws Exception {
+ String email = "email@android";
+ assertFalse("Should not match email: " + email,
+ Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+ }
+
+ public void testAutoLinkEmailAddress_doesNotMatchLocalPartEndingWithDot() throws Exception {
+ String email = "email.@android.com";
+ assertFalse("Should not match email: " + email,
+ Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+ }
+
+ public void testAutoLinkEmailAddress_doesNotMatchLocalPartStartingWithDot() throws Exception {
+ String email = ".email@android.com";
+ assertFalse("Should not match email: " + email,
+ Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+ }
+
+ public void testAutoLinkEmailAddress_doesNotMatchDomainStartingWithDash() throws Exception {
+ String email = "email@-android.com";
+ assertFalse("Should not match email: " + email,
+ Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+ }
+
+ public void testAutoLinkEmailAddress_doesNotMatchDomainWithConsecutiveDots() throws Exception {
+ String email = "email@android..com";
+ assertFalse("Should not match email: " + email,
+ Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+ }
+
+ public void testAutoLinkEmailAddress_doesNotMatchEmailWithIpAsDomain() throws Exception {
+ String email = "email@127.0.0.1";
+ assertFalse("Should not match email: " + email,
+ Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+ }
+
+ public void testAutoLinkEmailAddress_doesNotMatchEmailWithInvalidTld() throws Exception {
+ String email = "email@android.c";
+ assertFalse("Should not match email: " + email,
+ Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+ }
+
+ public void testAutoLinkEmailAddress_matchesLocalPartUpTo64Chars() throws Exception {
+ String localPart = "";
+ for (int i = 0; i < 64; i++) {
+ localPart += "a";
+ }
+ String email = localPart + "@android.com";
+
+ assertTrue("Should match local part of length: " + localPart.length(),
+ Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+
+ email = localPart + "a@android.com";
+ assertFalse("Should not match local part of length: " + localPart.length(),
+ Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+ }
+
+ public void testAutoLinkEmailAddress_matchesSubdomainUpTo63Chars() throws Exception {
+ String subdomain = "";
+ for (int i = 0; i < 63; i++) {
+ subdomain += "a";
+ }
+ String email = "email@" + subdomain + ".com";
+
+ assertTrue("Should match subdomain of length: " + subdomain.length(),
+ Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+
+ subdomain += "a";
+ email = "email@" + subdomain + ".com";
+ assertFalse("Should not match local part of length: " + subdomain.length(),
+ Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+ }
+
+ public void testAutoLinkEmailAddress_matchesDomainUpTo255Chars() throws Exception {
+ String longDomain = "";
+ while (longDomain.length() <= 250) {
+ longDomain += "d.";
+ }
+ longDomain += "com";
+ assertEquals(255, longDomain.length());
+ String email = "a@" + longDomain;
+
+ assertTrue("Should match domain of length: " + longDomain.length(),
+ Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+
+ email = email + "m";
+ assertEquals(258, email.length());
+ assertFalse("Should not match domain of length: " + longDomain.length(),
+ Patterns.AUTOLINK_EMAIL_ADDRESS.matcher(email).matches());
+ }
+
+ // Tests for Patterns.PHONE
@SmallTest
public void testPhonePattern() throws Exception {
diff --git a/core/tests/coretests/src/com/android/internal/inputmethod/InputMethodUtilsTest.java b/core/tests/coretests/src/com/android/internal/inputmethod/InputMethodUtilsTest.java
index ac020e4..719b274 100644
--- a/core/tests/coretests/src/com/android/internal/inputmethod/InputMethodUtilsTest.java
+++ b/core/tests/coretests/src/com/android/internal/inputmethod/InputMethodUtilsTest.java
@@ -70,6 +70,7 @@
private static final Locale LOCALE_TH_TH_TH = new Locale("ht", "TH", "TH");
private static final String SUBTYPE_MODE_KEYBOARD = "keyboard";
private static final String SUBTYPE_MODE_VOICE = "voice";
+ private static final String SUBTYPE_MODE_HANDWRITING = "handwriting";
private static final String SUBTYPE_MODE_ANY = null;
private static final String EXTRA_VALUE_PAIR_SEPARATOR = ",";
private static final String EXTRA_VALUE_ASCII_CAPABLE = "AsciiCapable";
@@ -215,6 +216,12 @@
final InputMethodSubtype nonAutoJa = createDummyInputMethodSubtype("ja",
SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE,
!IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE);
+ final InputMethodSubtype nonAutoHi = createDummyInputMethodSubtype("hi",
+ SUBTYPE_MODE_KEYBOARD, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE,
+ !IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE);
+ final InputMethodSubtype nonAutoHandwritingEn = createDummyInputMethodSubtype("en",
+ SUBTYPE_MODE_HANDWRITING, !IS_AUX, !IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE,
+ !IS_ASCII_CAPABLE, !IS_ENABLED_WHEN_DEFAULT_IS_NOT_ASCII_CAPABLE);
final InputMethodSubtype nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype =
createDummyInputMethodSubtype("zz", SUBTYPE_MODE_KEYBOARD, !IS_AUX,
!IS_OVERRIDES_IMPLICITLY_ENABLED_SUBTYPE, !IS_ASCII_CAPABLE,
@@ -349,6 +356,57 @@
verifyEquality(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype2, result.get(2));
}
+ // Make sure that if there is no subtype that matches the language requested, then we just
+ // use the first keyboard subtype.
+ {
+ final ArrayList<InputMethodSubtype> subtypes = new ArrayList<>();
+ subtypes.add(nonAutoHi);
+ subtypes.add(nonAutoEnUS);
+ subtypes.add(nonAutoHandwritingEn);
+ subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype);
+ final InputMethodInfo imi = createDummyInputMethodInfo(
+ "com.android.apps.inputmethod.latin",
+ "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT,
+ subtypes);
+ final ArrayList<InputMethodSubtype> result =
+ InputMethodUtils.getImplicitlyApplicableSubtypesLocked(
+ getResourcesForLocales(LOCALE_JA_JP), imi);
+ assertEquals(1, result.size());
+ verifyEquality(nonAutoHi, result.get(0));
+ }
+ {
+ final ArrayList<InputMethodSubtype> subtypes = new ArrayList<>();
+ subtypes.add(nonAutoEnUS);
+ subtypes.add(nonAutoHi);
+ subtypes.add(nonAutoHandwritingEn);
+ subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype);
+ final InputMethodInfo imi = createDummyInputMethodInfo(
+ "com.android.apps.inputmethod.latin",
+ "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT,
+ subtypes);
+ final ArrayList<InputMethodSubtype> result =
+ InputMethodUtils.getImplicitlyApplicableSubtypesLocked(
+ getResourcesForLocales(LOCALE_JA_JP), imi);
+ assertEquals(1, result.size());
+ verifyEquality(nonAutoEnUS, result.get(0));
+ }
+ {
+ final ArrayList<InputMethodSubtype> subtypes = new ArrayList<>();
+ subtypes.add(nonAutoHandwritingEn);
+ subtypes.add(nonAutoEnUS);
+ subtypes.add(nonAutoHi);
+ subtypes.add(nonAutoEnabledWhenDefaultIsNotAsciiCalableSubtype);
+ final InputMethodInfo imi = createDummyInputMethodInfo(
+ "com.android.apps.inputmethod.latin",
+ "com.android.apps.inputmethod.latin", "DummyLatinIme", !IS_AUX, IS_DEFAULT,
+ subtypes);
+ final ArrayList<InputMethodSubtype> result =
+ InputMethodUtils.getImplicitlyApplicableSubtypesLocked(
+ getResourcesForLocales(LOCALE_JA_JP), imi);
+ assertEquals(1, result.size());
+ verifyEquality(nonAutoEnUS, result.get(0));
+ }
+
// Make sure that 3-letter language code can be handled.
{
final ArrayList<InputMethodSubtype> subtypes = new ArrayList<>();
diff --git a/data/keyboards/qwerty2.kcm b/data/keyboards/qwerty2.kcm
index d96914f..b981d83 100644
--- a/data/keyboards/qwerty2.kcm
+++ b/data/keyboards/qwerty2.kcm
@@ -23,8 +23,8 @@
number: '2'
base: 'a'
shift, capslock: 'A'
- alt: 'a'
- shift+alt, capslock+alt: 'A'
+ alt: '\u00e1'
+ shift+alt, capslock+alt: '\u00c1'
}
key B {
@@ -41,8 +41,8 @@
number: '2'
base: 'c'
shift, capslock: 'C'
- alt: '\u00e7'
- shift+alt, capslock+alt: '\u00e7'
+ alt: '\u00a9'
+ shift+alt, capslock+alt: '\u00a2'
}
key D {
@@ -50,8 +50,8 @@
number: '3'
base: 'd'
shift, capslock: 'D'
- alt: '\''
- shift+alt, capslock+alt: '\''
+ alt: '\u00f0'
+ shift+alt, capslock+alt: '\u00d0'
}
key E {
@@ -59,8 +59,8 @@
number: '3'
base: 'e'
shift, capslock: 'E'
- alt: '"'
- shift+alt, capslock+alt: '\u0301'
+ alt: '\u00e9'
+ shift+alt, capslock+alt: '\u00c9'
}
key F {
@@ -95,8 +95,8 @@
number: '4'
base: 'i'
shift, capslock: 'I'
- alt: '-'
- shift+alt, capslock+alt: '\u0302'
+ alt: '\u00ed'
+ shift+alt, capslock+alt: '\u00cd'
}
key J {
@@ -122,8 +122,8 @@
number: '5'
base: 'l'
shift, capslock: 'L'
- alt: ':'
- shift+alt, capslock+alt: '`'
+ alt: '\u00f8'
+ shift+alt, capslock+alt: '\u00d8'
}
key M {
@@ -131,7 +131,7 @@
number: '6'
base: 'm'
shift, capslock: 'M'
- alt: '%'
+ alt: '\u00b5'
shift+alt, capslock+alt: none
}
@@ -140,8 +140,8 @@
number: '6'
base: 'n'
shift, capslock: 'N'
- alt: none
- shift+alt, capslock+alt: '\u0303'
+ alt: '\u00f1'
+ shift+alt, capslock+alt: '\u00d1'
}
key O {
@@ -149,8 +149,8 @@
number: '6'
base: 'o'
shift, capslock: 'O'
- alt: '+'
- shift+alt, capslock+alt: '+'
+ alt: '\u00f3'
+ shift+alt, capslock+alt: '\u00d3'
}
key P {
@@ -158,8 +158,8 @@
number: '7'
base: 'p'
shift, capslock: 'P'
- alt: '='
- shift+alt, capslock+alt: '\u00a5'
+ alt: '\u00f6'
+ shift+alt, capslock+alt: '\u00d6'
}
key Q {
@@ -167,8 +167,8 @@
number: '7'
base: 'q'
shift, capslock: 'Q'
- alt: '|'
- shift+alt, capslock+alt: '\u0300'
+ alt: '\u00e4'
+ shift+alt, capslock+alt: '\u00c4'
}
key R {
@@ -176,8 +176,8 @@
number: '7'
base: 'r'
shift, capslock: 'R'
- alt: '`'
- shift+alt, capslock+alt: '\u20ac'
+ alt: '\u00ae'
+ shift+alt, capslock+alt: 'R'
}
key S {
@@ -185,8 +185,8 @@
number: '7'
base: 's'
shift, capslock: 'S'
- alt: '\\'
- shift+alt, capslock+alt: '\u00df'
+ alt: '\u00df'
+ shift+alt, capslock+alt: '\u00a7'
}
key T {
@@ -194,8 +194,8 @@
number: '8'
base: 't'
shift, capslock: 'T'
- alt: '{'
- shift+alt, capslock+alt: '\u00a3'
+ alt: '\u00fe'
+ shift+alt, capslock+alt: '\u00de'
}
key U {
@@ -203,8 +203,8 @@
number: '8'
base: 'u'
shift, capslock: 'U'
- alt: '_'
- shift+alt, capslock+alt: '\u0308'
+ alt: '\u00fa'
+ shift+alt, capslock+alt: '\u00da'
}
key V {
@@ -221,8 +221,8 @@
number: '9'
base: 'w'
shift, capslock: 'W'
- alt: '~'
- shift+alt, capslock+alt: '~'
+ alt: '\u00e5'
+ shift+alt, capslock+alt: '\u00c5'
}
key X {
@@ -239,8 +239,8 @@
number: '9'
base: 'y'
shift, capslock: 'Y'
- alt: '}'
- shift+alt, capslock+alt: '\u00a1'
+ alt: '\u00fc'
+ shift+alt, capslock+alt: '\u00dc'
}
key Z {
@@ -248,8 +248,8 @@
number: '9'
base: 'z'
shift, capslock: 'Z'
- alt: 'z'
- shift+alt, capslock+alt: 'Z'
+ alt: '\u00e6'
+ shift+alt, capslock+alt: '\u00c6'
}
key COMMA {
@@ -257,8 +257,8 @@
number: ','
base: ','
shift: '<'
- alt: ','
- shift+alt: ','
+ alt: '\u00e7'
+ shift+alt: '\u00c7'
}
key PERIOD {
@@ -284,7 +284,7 @@
number: '/'
base: '/'
shift: '?'
- alt: '?'
+ alt: '\u00bf'
shift+alt: '?'
}
@@ -320,7 +320,7 @@
number: '0'
base: '0'
shift: ')'
- alt: ')'
+ alt: '\u02bc'
shift+alt: ')'
}
@@ -329,8 +329,8 @@
number: '1'
base: '1'
shift: '!'
- alt: '!'
- shift+alt: '!'
+ alt: '\u00a1'
+ shift+alt: '\u00b9'
}
key 2 {
@@ -338,7 +338,7 @@
number: '2'
base: '2'
shift: '@'
- alt: '@'
+ alt: '\u00b2'
shift+alt: '@'
}
@@ -347,7 +347,7 @@
number: '3'
base: '3'
shift: '#'
- alt: '#'
+ alt: '\u00b3'
shift+alt: '#'
}
@@ -356,8 +356,8 @@
number: '4'
base: '4'
shift: '$'
- alt: '$'
- shift+alt: '$'
+ alt: '\u00a4'
+ shift+alt: '\u00a3'
}
key 5 {
@@ -365,7 +365,7 @@
number: '5'
base: '5'
shift: '%'
- alt: '%'
+ alt: '\u20ac'
shift+alt: '%'
}
@@ -374,8 +374,8 @@
number: '6'
base: '6'
shift: '^'
- alt: '^'
- shift+alt: '^'
+ alt: '\u00bc'
+ shift+alt: '\u0302'
}
key 7 {
@@ -383,7 +383,7 @@
number: '7'
base: '7'
shift: '&'
- alt: '&'
+ alt: '\u00bd'
shift+alt: '&'
}
@@ -392,7 +392,7 @@
number: '8'
base: '8'
shift: '*'
- alt: '*'
+ alt: '\u00be'
shift+alt: '*'
}
@@ -401,7 +401,7 @@
number: '9'
base: '9'
shift: '('
- alt: '('
+ alt: '\u02bb'
shift+alt: '('
}
@@ -410,8 +410,8 @@
number: '`'
base: '`'
shift: '~'
- alt: '`'
- shift+alt: '~'
+ alt: '\u0300'
+ shift+alt: '\u0303'
}
key MINUS {
@@ -419,7 +419,7 @@
number: '-'
base: '-'
shift: '_'
- alt: '-'
+ alt: '\u00a5'
shift+alt: '_'
}
@@ -428,8 +428,8 @@
number: '='
base: '='
shift: '+'
- alt: '='
- shift+alt: '+'
+ alt: '\u00d7'
+ shift+alt: '\u00f7'
}
key LEFT_BRACKET {
@@ -437,7 +437,7 @@
number: '['
base: '['
shift: '{'
- alt: '['
+ alt: '\u00ab'
shift+alt: '{'
}
@@ -446,7 +446,7 @@
number: ']'
base: ']'
shift: '}'
- alt: ']'
+ alt: '\u00bb'
shift+alt: '}'
}
@@ -455,8 +455,8 @@
number: '\\'
base: '\\'
shift: '|'
- alt: '\\'
- shift+alt: '|'
+ alt: '\u00ac'
+ shift+alt: '\u00a6'
}
key SEMICOLON {
@@ -464,8 +464,8 @@
number: ';'
base: ';'
shift: ':'
- alt: ';'
- shift+alt: ':'
+ alt: '\u00b6'
+ shift+alt: '\u00b0'
}
key APOSTROPHE {
@@ -473,8 +473,8 @@
number: '\''
base: '\''
shift: '"'
- alt: '\''
- shift+alt: '"'
+ alt: '\u0301'
+ shift+alt: '\u0308'
}
key STAR {
diff --git a/docs/html/guide/topics/sensors/sensors_overview.jd b/docs/html/guide/topics/sensors/sensors_overview.jd
index 0b3cb2b..53faca0 100644
--- a/docs/html/guide/topics/sensors/sensors_overview.jd
+++ b/docs/html/guide/topics/sensors/sensors_overview.jd
@@ -465,6 +465,7 @@
...
mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
+mSensor = null;
if (mSensorManager.getDefaultSensor(Sensor.TYPE_GRAVITY) != null){
List<Sensor> gravSensors = mSensorManager.getSensorList(Sensor.TYPE_GRAVITY);
@@ -476,7 +477,7 @@
}
}
}
-else{
+if (mSensor == null){
// Use the accelerometer.
if (mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER) != null){
mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
diff --git a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
index 3901af3..ca214ab 100644
--- a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
+++ b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
@@ -40,6 +40,7 @@
import android.os.Build;
import android.util.ArrayMap;
import android.util.AttributeSet;
+import android.util.IntArray;
import android.util.Log;
import android.util.LongArray;
import android.util.PathParser;
@@ -629,12 +630,24 @@
*/
public void reset() {
ensureAnimatorSet();
+ if (DBG_ANIMATION_VECTOR_DRAWABLE) {
+ Log.w(LOGTAG, "calling reset on AVD: " +
+ ((VectorDrawable.VectorDrawableState) ((AnimatedVectorDrawableState)
+ getConstantState()).mVectorDrawable.getConstantState()).mRootName
+ + ", at: " + this);
+ }
mAnimatorSet.reset();
}
@Override
public void start() {
ensureAnimatorSet();
+ if (DBG_ANIMATION_VECTOR_DRAWABLE) {
+ Log.w(LOGTAG, "calling start on AVD: " +
+ ((VectorDrawable.VectorDrawableState) ((AnimatedVectorDrawableState)
+ getConstantState()).mVectorDrawable.getConstantState()).mRootName
+ + ", at: " + this);
+ }
mAnimatorSet.start();
}
@@ -652,6 +665,12 @@
@Override
public void stop() {
+ if (DBG_ANIMATION_VECTOR_DRAWABLE) {
+ Log.w(LOGTAG, "calling stop on AVD: " +
+ ((VectorDrawable.VectorDrawableState) ((AnimatedVectorDrawableState)
+ getConstantState()).mVectorDrawable.getConstantState())
+ .mRootName + ", at: " + this);
+ }
mAnimatorSet.end();
}
@@ -864,9 +883,10 @@
* @hide
*/
public static class VectorDrawableAnimatorRT implements VectorDrawableAnimator {
- private static final int NONE = 0;
private static final int START_ANIMATION = 1;
private static final int REVERSE_ANIMATION = 2;
+ private static final int RESET_ANIMATION = 3;
+ private static final int END_ANIMATION = 4;
private AnimatorListener mListener = null;
private final LongArray mStartDelays = new LongArray();
private PropertyValuesHolder.PropertyValues mTmpValues =
@@ -882,7 +902,7 @@
private final VirtualRefBasePtr mSetRefBasePtr;
private WeakReference<RenderNode> mLastSeenTarget = null;
private int mLastListenerId = 0;
- private int mPendingAnimationAction = NONE;
+ private final IntArray mPendingAnimationActions = new IntArray();
private final Drawable mDrawable;
VectorDrawableAnimatorRT(AnimatedVectorDrawable drawable) {
@@ -1139,16 +1159,29 @@
protected void recordLastSeenTarget(DisplayListCanvas canvas) {
mLastSeenTarget = new WeakReference<RenderNode>(
RenderNodeAnimatorSetHelper.getTarget(canvas));
- if (mPendingAnimationAction != NONE) {
+ if (mPendingAnimationActions.size() > 0 && useLastSeenTarget()) {
if (DBG_ANIMATION_VECTOR_DRAWABLE) {
Log.d(LOGTAG, "Target is set in the next frame");
}
- if (mPendingAnimationAction == START_ANIMATION) {
- start();
- } else if (mPendingAnimationAction == REVERSE_ANIMATION) {
- reverse();
+ for (int i = 0; i < mPendingAnimationActions.size(); i++) {
+ handlePendingAction(mPendingAnimationActions.get(i));
}
- mPendingAnimationAction = NONE;
+ mPendingAnimationActions.clear();
+ }
+ }
+
+ private void handlePendingAction(int pendingAnimationAction) {
+ if (pendingAnimationAction == START_ANIMATION) {
+ startAnimation();
+ } else if (pendingAnimationAction == REVERSE_ANIMATION) {
+ reverseAnimation();
+ } else if (pendingAnimationAction == RESET_ANIMATION) {
+ resetAnimation();
+ } else if (pendingAnimationAction == END_ANIMATION) {
+ endAnimation();
+ } else {
+ throw new UnsupportedOperationException("Animation action " +
+ pendingAnimationAction + "is not supported");
}
}
@@ -1167,45 +1200,51 @@
mDrawable.invalidateSelf();
}
+ private void addPendingAction(int pendingAnimationAction) {
+ invalidateOwningView();
+ mPendingAnimationActions.add(pendingAnimationAction);
+ }
+
@Override
public void start() {
if (!mInitialized) {
return;
}
- if (!useLastSeenTarget()) {
- invalidateOwningView();
- mPendingAnimationAction = START_ANIMATION;
- return;
+ if (useLastSeenTarget()) {
+ if (DBG_ANIMATION_VECTOR_DRAWABLE) {
+ Log.d(LOGTAG, "Target is set. Starting VDAnimatorSet from java");
+ }
+ startAnimation();
+ } else {
+ addPendingAction(START_ANIMATION);
}
- if (DBG_ANIMATION_VECTOR_DRAWABLE) {
- Log.d(LOGTAG, "Target is set. Starting VDAnimatorSet from java");
- }
-
- mStarted = true;
- nStart(mSetPtr, this, ++mLastListenerId);
- invalidateOwningView();
- if (mListener != null) {
- mListener.onAnimationStart(null);
- }
}
@Override
public void end() {
- if (mInitialized && useLastSeenTarget()) {
- // If no target has ever been set, no-op
- nEnd(mSetPtr);
- invalidateOwningView();
+ if (!mInitialized) {
+ return;
+ }
+
+ if (useLastSeenTarget()) {
+ endAnimation();
+ } else {
+ addPendingAction(END_ANIMATION);
}
}
@Override
public void reset() {
- if (mInitialized && useLastSeenTarget()) {
- // If no target has ever been set, no-op
- nReset(mSetPtr);
- invalidateOwningView();
+ if (!mInitialized) {
+ return;
+ }
+
+ if (useLastSeenTarget()) {
+ resetAnimation();
+ } else {
+ addPendingAction(RESET_ANIMATION);
}
}
@@ -1216,15 +1255,53 @@
if (!mIsReversible || !mInitialized) {
return;
}
- if (!useLastSeenTarget()) {
- invalidateOwningView();
- mPendingAnimationAction = REVERSE_ANIMATION;
- return;
+ if (useLastSeenTarget()) {
+ if (DBG_ANIMATION_VECTOR_DRAWABLE) {
+ Log.d(LOGTAG, "Target is set. Reversing VDAnimatorSet from java");
+ }
+ reverseAnimation();
+ } else {
+ addPendingAction(REVERSE_ANIMATION);
}
+ }
+
+ // This should only be called after animator has been added to the RenderNode target.
+ private void startAnimation() {
if (DBG_ANIMATION_VECTOR_DRAWABLE) {
- Log.d(LOGTAG, "Target is set. Reversing VDAnimatorSet from java");
+ Log.w(LOGTAG, "starting animation on VD: " +
+ ((VectorDrawable.VectorDrawableState) ((AnimatedVectorDrawableState)
+ mDrawable.getConstantState()).mVectorDrawable.getConstantState())
+ .mRootName);
}
mStarted = true;
+ nStart(mSetPtr, this, ++mLastListenerId);
+ invalidateOwningView();
+ if (mListener != null) {
+ mListener.onAnimationStart(null);
+ }
+ }
+
+ // This should only be called after animator has been added to the RenderNode target.
+ private void endAnimation() {
+ if (DBG_ANIMATION_VECTOR_DRAWABLE) {
+ Log.w(LOGTAG, "ending animation on VD: " +
+ ((VectorDrawable.VectorDrawableState) ((AnimatedVectorDrawableState)
+ mDrawable.getConstantState()).mVectorDrawable.getConstantState())
+ .mRootName);
+ }
+ nEnd(mSetPtr);
+ invalidateOwningView();
+ }
+
+ // This should only be called after animator has been added to the RenderNode target.
+ private void resetAnimation() {
+ nReset(mSetPtr);
+ invalidateOwningView();
+ }
+
+ // This should only be called after animator has been added to the RenderNode target.
+ private void reverseAnimation() {
+ mStarted = true;
nReverse(mSetPtr, this, ++mLastListenerId);
invalidateOwningView();
if (mListener != null) {
diff --git a/include/androidfw/ResourceTypes.h b/include/androidfw/ResourceTypes.h
index d8801b8..f23fceb 100644
--- a/include/androidfw/ResourceTypes.h
+++ b/include/androidfw/ResourceTypes.h
@@ -1151,9 +1151,13 @@
uint32_t screenConfig2;
};
- // If true, it means that the script of the locale was explicitly provided.
- // If false, it means that the script was automatically computed.
- bool localeScriptWasProvided;
+ // If false and localeScript is set, it means that the script of the locale
+ // was explicitly provided.
+ //
+ // If true, it means that localeScript was automatically computed.
+ // localeScript may still not be set in this case, which means that we
+ // tried but could not compute a script.
+ bool localeScriptWasComputed;
void copyFromDeviceNoSwap(const ResTable_config& o);
@@ -1233,7 +1237,7 @@
inline void clearLocale() {
locale = 0;
- localeScriptWasProvided = false;
+ localeScriptWasComputed = false;
memset(localeScript, 0, sizeof(localeScript));
memset(localeVariant, 0, sizeof(localeVariant));
}
@@ -1896,6 +1900,13 @@
mutable Mutex mLock;
+ // Mutex that controls access to the list of pre-filtered configurations
+ // to check when looking up entries.
+ // When iterating over a bag, the mLock mutex is locked. While mLock is locked,
+ // we do resource lookups.
+ // Mutex is not reentrant, so we must use a different lock than mLock.
+ mutable Mutex mFilteredConfigLock;
+
status_t mError;
ResTable_config mParams;
diff --git a/keystore/java/android/security/KeyChain.java b/keystore/java/android/security/KeyChain.java
index 7adad8a..0886487 100644
--- a/keystore/java/android/security/KeyChain.java
+++ b/keystore/java/android/security/KeyChain.java
@@ -547,11 +547,8 @@
Intent intent = new Intent(IKeyChainService.class.getName());
ComponentName comp = intent.resolveSystemService(context.getPackageManager(), 0);
intent.setComponent(comp);
- boolean isBound = context.bindServiceAsUser(intent,
- keyChainServiceConnection,
- Context.BIND_AUTO_CREATE,
- user);
- if (!isBound) {
+ if (comp == null || !context.bindServiceAsUser(
+ intent, keyChainServiceConnection, Context.BIND_AUTO_CREATE, user)) {
throw new AssertionError("could not bind to KeyChainService");
}
return new KeyChainConnection(context, keyChainServiceConnection, q.take());
diff --git a/libs/androidfw/ResourceTypes.cpp b/libs/androidfw/ResourceTypes.cpp
index 3277c36..49b3a51 100644
--- a/libs/androidfw/ResourceTypes.cpp
+++ b/libs/androidfw/ResourceTypes.cpp
@@ -25,6 +25,7 @@
#include <string.h>
#include <limits>
+#include <memory>
#include <type_traits>
#include <androidfw/ByteBucketArray.h>
@@ -1869,8 +1870,8 @@
// The language & region are equal, so compare the scripts and variants.
const char emptyScript[sizeof(l.localeScript)] = {'\0', '\0', '\0', '\0'};
- const char *lScript = l.localeScriptWasProvided ? l.localeScript : emptyScript;
- const char *rScript = r.localeScriptWasProvided ? r.localeScript : emptyScript;
+ const char *lScript = l.localeScriptWasComputed ? emptyScript : l.localeScript;
+ const char *rScript = r.localeScriptWasComputed ? emptyScript : r.localeScript;
int script = memcmp(lScript, rScript, sizeof(l.localeScript));
if (script) {
return script;
@@ -2015,11 +2016,11 @@
// scripts since it seems more useful to do so. We will consider
// "en-US-POSIX" to be more specific than "en-Latn-US".
- const int score = (localeScriptWasProvided ? 1 : 0) +
- ((localeVariant[0] != 0) ? 2 : 0);
+ const int score = ((localeScript[0] != '\0' && !localeScriptWasComputed) ? 1 : 0) +
+ ((localeVariant[0] != '\0') ? 2 : 0);
- const int oScore = (o.localeScriptWasProvided ? 1 : 0) +
- ((o.localeVariant[0] != 0) ? 2 : 0);
+ const int oScore = (o.localeScript[0] != '\0' && !o.localeScriptWasComputed ? 1 : 0) +
+ ((o.localeVariant[0] != '\0') ? 2 : 0);
return score - oScore;
@@ -2534,7 +2535,8 @@
if (settings.localeScript[0] == '\0') { // could not determine the request's script
countriesMustMatch = true;
} else {
- if (localeScript[0] == '\0') { // script was not provided, so we try to compute it
+ if (localeScript[0] == '\0' && !localeScriptWasComputed) {
+ // script was not provided or computed, so we try to compute it
localeDataComputeScript(computed_script, language, country);
if (computed_script[0] == '\0') { // we could not compute the script
countriesMustMatch = true;
@@ -2683,8 +2685,8 @@
if (!language[0]) {
return;
}
-
- if (!localeScriptWasProvided && !localeVariant[0]) {
+ const bool scriptWasProvided = localeScript[0] != '\0' && !localeScriptWasComputed;
+ if (!scriptWasProvided && !localeVariant[0]) {
// Legacy format.
if (out.size() > 0) {
out.append("-");
@@ -2714,7 +2716,7 @@
size_t len = unpackLanguage(buf);
out.append(buf, len);
- if (localeScriptWasProvided) {
+ if (scriptWasProvided) {
out.append("+");
out.append(localeScript, sizeof(localeScript));
}
@@ -2745,7 +2747,7 @@
charsWritten += unpackLanguage(str);
}
- if (localeScriptWasProvided) {
+ if (localeScript[0] && !localeScriptWasComputed) {
if (charsWritten) {
str[charsWritten++] = '-';
}
@@ -2786,7 +2788,6 @@
for (size_t i = 1; i < 4; ++i) {
config->localeScript[i] = tolower(start[i]);
}
- config->localeScriptWasProvided = true;
break;
}
case 5:
@@ -2806,7 +2807,6 @@
void ResTable_config::setBcp47Locale(const char* in) {
locale = 0;
- localeScriptWasProvided = false;
memset(localeScript, 0, sizeof(localeScript));
memset(localeVariant, 0, sizeof(localeVariant));
@@ -2823,9 +2823,10 @@
const size_t size = in + strlen(in) - start;
assignLocaleComponent(this, start, size);
- if (localeScript[0] == '\0') {
+ localeScriptWasComputed = (localeScript[0] == '\0');
+ if (localeScriptWasComputed) {
computeScript();
- };
+ }
}
String8 ResTable_config::toString() const {
@@ -3146,6 +3147,9 @@
StringPoolRef keyStr;
};
+template <typename T>
+using SharedVector = std::shared_ptr<Vector<T>>;
+
struct ResTable::Type
{
Type(const Header* _header, const Package* _package, size_t count)
@@ -3158,6 +3162,10 @@
const uint32_t* typeSpecFlags;
IdmapEntries idmapEntries;
Vector<const ResTable_type*> configs;
+
+ // The set of configurations that match the current parameters.
+ // This will be swapped with a new set when the parameters change.
+ SharedVector<const ResTable_type*> filteredConfigs;
};
struct ResTable::Package
@@ -4430,18 +4438,44 @@
void ResTable::setParameters(const ResTable_config* params)
{
- mLock.lock();
+ AutoMutex _lock(mLock);
+ AutoMutex _lock2(mFilteredConfigLock);
+
if (kDebugTableGetEntry) {
ALOGI("Setting parameters: %s\n", params->toString().string());
}
mParams = *params;
- for (size_t i=0; i<mPackageGroups.size(); i++) {
+ for (size_t p = 0; p < mPackageGroups.size(); p++) {
+ PackageGroup* packageGroup = mPackageGroups.editItemAt(p);
if (kDebugTableNoisy) {
- ALOGI("CLEARING BAGS FOR GROUP %zu!", i);
+ ALOGI("CLEARING BAGS FOR GROUP %zu!", p);
}
- mPackageGroups[i]->clearBagCache();
+ packageGroup->clearBagCache();
+
+ for (size_t t = 0; t < packageGroup->types.size(); t++) {
+ TypeList& typeList = packageGroup->types.editItemAt(t);
+ for (size_t ts = 0; ts < typeList.size(); ts++) {
+ Type* type = typeList.editItemAt(ts);
+
+ SharedVector<const ResTable_type*> newFilteredConfigs =
+ std::make_shared<Vector<const ResTable_type*>>();
+ for (size_t ti = 0; ti < type->configs.size(); ti++) {
+ ResTable_config config;
+ config.copyFromDtoH(type->configs[ti]->config);
+
+ if (config.match(mParams)) {
+ newFilteredConfigs->add(type->configs[ti]);
+ }
+ }
+
+ if (kDebugTableNoisy) {
+ ALOGD("Updating pkg=%zu type=%zu with %zu filtered configs",
+ p, t, newFilteredConfigs->size());
+ }
+ type->filteredConfigs = newFilteredConfigs;
+ }
+ }
}
- mLock.unlock();
}
void ResTable::getParameters(ResTable_config* params) const
@@ -5974,9 +6008,29 @@
specFlags = -1;
}
- const size_t numConfigs = typeSpec->configs.size();
+ const Vector<const ResTable_type*>* candidateConfigs = &typeSpec->configs;
+
+ SharedVector<const ResTable_type*> filteredConfigs;
+ if (config && memcmp(&mParams, config, sizeof(mParams)) == 0) {
+ // Grab the lock first so we can safely get the current filtered list.
+ AutoMutex _lock(mFilteredConfigLock);
+
+ // This configuration is equal to the one we have previously cached for,
+ // so use the filtered configs.
+
+ if (typeSpec->filteredConfigs) {
+ // Grab a reference to the shared_ptr so it doesn't get destroyed while
+ // going through this list.
+ filteredConfigs = typeSpec->filteredConfigs;
+
+ // Use this filtered list.
+ candidateConfigs = filteredConfigs.get();
+ }
+ }
+
+ const size_t numConfigs = candidateConfigs->size();
for (size_t c = 0; c < numConfigs; c++) {
- const ResTable_type* const thisType = typeSpec->configs[c];
+ const ResTable_type* const thisType = candidateConfigs->itemAt(c);
if (thisType == NULL) {
continue;
}
diff --git a/libs/androidfw/tests/ConfigLocale_test.cpp b/libs/androidfw/tests/ConfigLocale_test.cpp
index 4b8d65c..2bf9b12 100644
--- a/libs/androidfw/tests/ConfigLocale_test.cpp
+++ b/libs/androidfw/tests/ConfigLocale_test.cpp
@@ -125,10 +125,10 @@
if (script != NULL) {
memcpy(out->localeScript, script, 4);
- out->localeScriptWasProvided = true;
+ out->localeScriptWasComputed = false;
} else {
out->computeScript();
- out->localeScriptWasProvided = false;
+ out->localeScriptWasComputed = true;
}
if (variant != NULL) {
@@ -182,7 +182,7 @@
EXPECT_EQ('n', test.language[1]);
EXPECT_EQ('U', test.country[0]);
EXPECT_EQ('S', test.country[1]);
- EXPECT_FALSE(test.localeScriptWasProvided);
+ EXPECT_TRUE(test.localeScriptWasComputed);
EXPECT_EQ(0, memcmp("Latn", test.localeScript, 4));
EXPECT_EQ(0, test.localeVariant[0]);
@@ -203,7 +203,7 @@
EXPECT_EQ('e', test.language[0]);
EXPECT_EQ('n', test.language[1]);
EXPECT_EQ(0, memcmp("Latn", test.localeScript, 4));
- EXPECT_TRUE(test.localeScriptWasProvided);
+ EXPECT_FALSE(test.localeScriptWasComputed);
memset(out, 1, 4);
test.unpackRegion(out);
EXPECT_EQ('4', out[0]);
@@ -216,7 +216,7 @@
EXPECT_EQ('d', out[0]);
EXPECT_EQ('e', out[1]);
EXPECT_EQ('\0', out[2]);
- EXPECT_FALSE(test.localeScriptWasProvided);
+ EXPECT_TRUE(test.localeScriptWasComputed);
EXPECT_EQ(0, memcmp("Latn", test.localeScript, 4));
memset(out, 1, 4);
test.unpackRegion(out);
@@ -229,7 +229,7 @@
EXPECT_EQ('d', out[0]);
EXPECT_EQ('e', out[1]);
EXPECT_EQ('\0', out[2]);
- EXPECT_TRUE(test.localeScriptWasProvided);
+ EXPECT_FALSE(test.localeScriptWasComputed);
EXPECT_EQ(0, memcmp("Latn", test.localeScript, 4));
memset(out, 1, 4);
test.unpackRegion(out);
@@ -270,11 +270,11 @@
fillIn("en", NULL, "Latn", NULL, &config);
char out[RESTABLE_MAX_LOCALE_LEN];
- config.localeScriptWasProvided = true;
+ config.localeScriptWasComputed = false;
config.getBcp47Locale(out);
EXPECT_EQ(0, strcmp("en-Latn", out));
- config.localeScriptWasProvided = false;
+ config.localeScriptWasComputed = true;
config.getBcp47Locale(out);
EXPECT_EQ(0, strcmp("en", out));
}
@@ -379,7 +379,7 @@
// emulate packages built with older AAPT
memset(supported.localeScript, '\0', 4);
- supported.localeScriptWasProvided = false;
+ supported.localeScriptWasComputed = false;
EXPECT_TRUE(supported.match(requested));
}
diff --git a/libs/hwui/BakedOpDispatcher.cpp b/libs/hwui/BakedOpDispatcher.cpp
index 1aab3c7..06b712e 100644
--- a/libs/hwui/BakedOpDispatcher.cpp
+++ b/libs/hwui/BakedOpDispatcher.cpp
@@ -30,6 +30,7 @@
#include <algorithm>
#include <math.h>
#include <SkPaintDefaults.h>
+#include <SkPathOps.h>
namespace android {
namespace uirenderer {
@@ -60,7 +61,10 @@
for (size_t i = 0; i < opList.count; i++) {
const BakedOpState& state = *(opList.states[i]);
TextureVertex* rectVerts = &vertices[i * 4];
- Rect opBounds = state.computedState.clippedBounds;
+
+ // calculate unclipped bounds, since they'll determine texture coordinates
+ Rect opBounds = state.op->unmappedBounds;
+ state.computedState.transform.mapRect(opBounds);
if (CC_LIKELY(state.computedState.transform.isPureTranslate())) {
// pure translate, so snap (same behavior as onBitmapOp)
opBounds.snapToPixelBoundaries();
@@ -527,6 +531,12 @@
SkPath path;
SkRect rect = getBoundsOfFill(op);
path.addOval(rect);
+
+ if (state.computedState.localProjectionPathMask != nullptr) {
+ // Mask the ripple path by the local space projection mask in local space.
+ // Note that this can create CCW paths.
+ Op(path, *state.computedState.localProjectionPathMask, kIntersect_SkPathOp, &path);
+ }
renderConvexPath(renderer, state, path, *(op.paint));
}
}
diff --git a/libs/hwui/BakedOpState.cpp b/libs/hwui/BakedOpState.cpp
index 682bd04..26653f7 100644
--- a/libs/hwui/BakedOpState.cpp
+++ b/libs/hwui/BakedOpState.cpp
@@ -63,9 +63,22 @@
clipState = nullptr;
clippedBounds.setEmpty();
} else {
- // Not rejected! compute true clippedBounds and clipSideFlags
+ // Not rejected! compute true clippedBounds, clipSideFlags, and path mask
clipSideFlags = computeClipSideFlags(clipRect, clippedBounds);
clippedBounds.doIntersect(clipRect);
+
+ if (CC_UNLIKELY(snapshot.projectionPathMask)) {
+ // map projection path mask from render target space into op space,
+ // so intersection with op geometry is possible
+ Matrix4 inverseTransform;
+ inverseTransform.loadInverse(transform);
+ SkMatrix skInverseTransform;
+ inverseTransform.copyTo(skInverseTransform);
+
+ auto localMask = allocator.create<SkPath>();
+ snapshot.projectionPathMask->transform(skInverseTransform, localMask);
+ localProjectionPathMask = localMask;
+ }
}
}
@@ -73,13 +86,15 @@
: transform(*snapshot.transform)
, clipState(snapshot.mutateClipArea().serializeClip(allocator))
, clippedBounds(clipState->rect)
- , clipSideFlags(OpClipSideFlags::Full) {}
+ , clipSideFlags(OpClipSideFlags::Full)
+ , localProjectionPathMask(nullptr) {}
ResolvedRenderState::ResolvedRenderState(const ClipRect* clipRect, const Rect& dstRect)
: transform(Matrix4::identity())
, clipState(clipRect)
, clippedBounds(dstRect)
- , clipSideFlags(computeClipSideFlags(clipRect->rect, dstRect)) {
+ , clipSideFlags(computeClipSideFlags(clipRect->rect, dstRect))
+ , localProjectionPathMask(nullptr) {
clippedBounds.doIntersect(clipRect->rect);
}
diff --git a/libs/hwui/BakedOpState.h b/libs/hwui/BakedOpState.h
index 4365ef8..ffe2901 100644
--- a/libs/hwui/BakedOpState.h
+++ b/libs/hwui/BakedOpState.h
@@ -88,6 +88,7 @@
const ClipBase* clipState = nullptr;
Rect clippedBounds;
int clipSideFlags = 0;
+ const SkPath* localProjectionPathMask = nullptr;
};
/**
@@ -154,7 +155,6 @@
// simple state (straight pointer/value storage):
const float alpha;
const RoundRectClipState* roundRectClipState;
- const ProjectionPathMask* projectionPathMask;
const RecordedOp* op;
private:
@@ -165,21 +165,18 @@
: computedState(allocator, snapshot, recordedOp, expandForStroke)
, alpha(snapshot.alpha)
, roundRectClipState(snapshot.roundRectClipState)
- , projectionPathMask(snapshot.projectionPathMask)
, op(&recordedOp) {}
BakedOpState(LinearAllocator& allocator, Snapshot& snapshot, const ShadowOp* shadowOpPtr)
: computedState(allocator, snapshot)
, alpha(snapshot.alpha)
, roundRectClipState(snapshot.roundRectClipState)
- , projectionPathMask(snapshot.projectionPathMask)
, op(shadowOpPtr) {}
BakedOpState(const ClipRect* clipRect, const Rect& dstRect, const RecordedOp& recordedOp)
: computedState(clipRect, dstRect)
, alpha(1.0f)
, roundRectClipState(nullptr)
- , projectionPathMask(nullptr)
, op(&recordedOp) {}
};
diff --git a/libs/hwui/FrameBuilder.cpp b/libs/hwui/FrameBuilder.cpp
index 04de98a..5642170 100644
--- a/libs/hwui/FrameBuilder.cpp
+++ b/libs/hwui/FrameBuilder.cpp
@@ -389,34 +389,38 @@
}
void FrameBuilder::deferProjectedChildren(const RenderNode& renderNode) {
- const SkPath* projectionReceiverOutline = renderNode.properties().getOutline().getPath();
int count = mCanvasState.save(SaveFlags::MatrixClip);
+ const SkPath* projectionReceiverOutline = renderNode.properties().getOutline().getPath();
- // can't be null, since DL=null node rejection happens before deferNodePropsAndOps
- const DisplayList& displayList = *(renderNode.getDisplayList());
-
- const RecordedOp* op = (displayList.getOps()[displayList.projectionReceiveIndex]);
- const RenderNodeOp* backgroundOp = static_cast<const RenderNodeOp*>(op);
- const RenderProperties& backgroundProps = backgroundOp->renderNode->properties();
-
- // Transform renderer to match background we're projecting onto
- // (by offsetting canvas by translationX/Y of background rendernode, since only those are set)
- mCanvasState.translate(backgroundProps.getTranslationX(), backgroundProps.getTranslationY());
-
- // If the projection receiver has an outline, we mask projected content to it
- // (which we know, apriori, are all tessellated paths)
- mCanvasState.setProjectionPathMask(mAllocator, projectionReceiverOutline);
-
- // draw projected nodes
- for (size_t i = 0; i < renderNode.mProjectedNodes.size(); i++) {
- RenderNodeOp* childOp = renderNode.mProjectedNodes[i];
-
- int restoreTo = mCanvasState.save(SaveFlags::Matrix);
- mCanvasState.concatMatrix(childOp->transformFromCompositingAncestor);
- deferRenderNodeOpImpl(*childOp);
- mCanvasState.restoreToCount(restoreTo);
+ SkPath transformedMaskPath; // on stack, since BakedOpState makes a deep copy
+ if (projectionReceiverOutline) {
+ // transform the mask for this projector into render target space
+ // TODO: consider combining both transforms by stashing transform instead of applying
+ SkMatrix skCurrentTransform;
+ mCanvasState.currentTransform()->copyTo(skCurrentTransform);
+ projectionReceiverOutline->transform(
+ skCurrentTransform,
+ &transformedMaskPath);
+ mCanvasState.setProjectionPathMask(mAllocator, &transformedMaskPath);
}
+ for (size_t i = 0; i < renderNode.mProjectedNodes.size(); i++) {
+ RenderNodeOp* childOp = renderNode.mProjectedNodes[i];
+ RenderNode& childNode = *childOp->renderNode;
+
+ // Draw child if it has content, but ignore state in childOp - matrix already applied to
+ // transformFromCompositingAncestor, and record-time clip is ignored when projecting
+ if (!childNode.nothingToDraw()) {
+ int restoreTo = mCanvasState.save(SaveFlags::MatrixClip);
+
+ // Apply transform between ancestor and projected descendant
+ mCanvasState.concatMatrix(childOp->transformFromCompositingAncestor);
+
+ deferNodePropsAndOps(childNode);
+
+ mCanvasState.restoreToCount(restoreTo);
+ }
+ }
mCanvasState.restoreToCount(count);
}
@@ -513,10 +517,6 @@
BakedOpState* bakedState = tryBakeOpState(op);
if (!bakedState) return; // quick rejected
- currentLayer().deferUnmergeableOp(mAllocator, bakedState, OpBatchType::Bitmap);
-
- // TODO: Fix this ( b/26569206 )
-/*
// Don't merge non-simply transformed or neg scale ops, SET_TEXTURE doesn't handle rotation
// Don't merge A8 bitmaps - the paint's color isn't compared by mergeId, or in
// MergingDrawBatch::canMergeWith()
@@ -531,7 +531,6 @@
} else {
currentLayer().deferUnmergeableOp(mAllocator, bakedState, OpBatchType::Bitmap);
}
-*/
}
void FrameBuilder::deferBitmapMeshOp(const BitmapMeshOp& op) {
diff --git a/libs/hwui/LayerBuilder.cpp b/libs/hwui/LayerBuilder.cpp
index bc39621..c5af279 100644
--- a/libs/hwui/LayerBuilder.cpp
+++ b/libs/hwui/LayerBuilder.cpp
@@ -140,7 +140,10 @@
// Identical round rect clip state means both ops will clip in the same way, or not at all.
// As the state objects are const, we can compare their pointers to determine mergeability
if (lhs->roundRectClipState != rhs->roundRectClipState) return false;
- if (lhs->projectionPathMask != rhs->projectionPathMask) return false;
+
+ // Local masks prevent merge, since they're potentially in different coordinate spaces
+ if (lhs->computedState.localProjectionPathMask
+ || rhs->computedState.localProjectionPathMask) return false;
/* Clipping compatibility check
*
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index b7a5923..7693fdc 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -1148,7 +1148,9 @@
// always store/restore, since these are just pointers
state.mRoundRectClipState = currentSnapshot()->roundRectClipState;
+#if !HWUI_NEW_OPS
state.mProjectionPathMask = currentSnapshot()->projectionPathMask;
+#endif
return false;
}
@@ -1156,7 +1158,9 @@
setGlobalMatrix(state.mMatrix);
writableSnapshot()->alpha = state.mAlpha;
writableSnapshot()->roundRectClipState = state.mRoundRectClipState;
+#if !HWUI_NEW_OPS
writableSnapshot()->projectionPathMask = state.mProjectionPathMask;
+#endif
if (state.mClipValid && !skipClipRestore) {
writableSnapshot()->setClip(state.mClip.left, state.mClip.top,
@@ -1833,6 +1837,7 @@
path.addCircle(x, y, radius);
}
+#if !HWUI_NEW_OPS
if (CC_UNLIKELY(currentSnapshot()->projectionPathMask != nullptr)) {
// mask ripples with projection mask
SkPath maskPath = *(currentSnapshot()->projectionPathMask->projectionMask);
@@ -1852,6 +1857,7 @@
// in local space. Note that this can create CCW paths.
Op(path, maskPath, kIntersect_SkPathOp, &path);
}
+#endif
drawConvexPath(path, p);
}
diff --git a/libs/hwui/RecordingCanvas.cpp b/libs/hwui/RecordingCanvas.cpp
index 9ae2212..ddf0528 100644
--- a/libs/hwui/RecordingCanvas.cpp
+++ b/libs/hwui/RecordingCanvas.cpp
@@ -24,6 +24,14 @@
namespace android {
namespace uirenderer {
+
+static Rect sUnreasonablyLargeBounds(-10000, -10000, 10000, 10000);
+
+static const Rect& getConservativeOpBounds(const ClipBase* clip) {
+ // if op is clipped, that rect can be used, but otherwise just use a conservatively large rect
+ return clip ? clip->rect : sUnreasonablyLargeBounds;
+}
+
RecordingCanvas::RecordingCanvas(size_t width, size_t height)
: mState(*this)
, mResourceCache(ResourceCache::getInstance()) {
@@ -242,10 +250,8 @@
void RecordingCanvas::drawPaint(const SkPaint& paint) {
const ClipBase* clip = getRecordedClip();
- // if there's no current clip, draw a big rect and hope we cover the eventual clip bounds
- Rect bounds = clip ? clip->rect : Rect(-10000, -10000, 10000, 10000);
addOp(alloc().create_trivial<RectOp>(
- bounds,
+ getConservativeOpBounds(clip),
Matrix4::identity(),
clip,
refPaint(&paint)));
@@ -534,10 +540,11 @@
float hOffset, float vOffset, const SkPaint& paint) {
if (!glyphs || glyphCount <= 0 || PaintUtils::paintWillNotDrawText(paint)) return;
glyphs = refBuffer<glyph_t>(glyphs, glyphCount);
+ auto clip = getRecordedClip();
addOp(alloc().create_trivial<TextOnPathOp>(
- mState.getLocalClipBounds(), // TODO: explicitly define bounds
+ getConservativeOpBounds(clip), // TODO: explicitly define bounds
*(mState.currentSnapshot()->transform),
- getRecordedClip(),
+ clip,
refPaint(&paint), glyphs, glyphCount, refPath(&path), hOffset, vOffset));
}
@@ -586,10 +593,11 @@
void RecordingCanvas::callDrawGLFunction(Functor* functor) {
mDisplayList->functors.push_back(functor);
+ auto clip = getRecordedClip();
addOp(alloc().create_trivial<FunctorOp>(
- mState.getLocalClipBounds(), // TODO: explicitly define bounds
+ getConservativeOpBounds(clip), // TODO: explicitly define bounds
*(mState.currentSnapshot()->transform),
- getRecordedClip(),
+ clip,
functor));
}
diff --git a/libs/hwui/Snapshot.cpp b/libs/hwui/Snapshot.cpp
index 27fea1f..cf5e69a 100644
--- a/libs/hwui/Snapshot.cpp
+++ b/libs/hwui/Snapshot.cpp
@@ -146,6 +146,9 @@
}
void Snapshot::buildScreenSpaceTransform(Matrix4* outTransform) const {
+#if HWUI_NEW_OPS
+ LOG_ALWAYS_FATAL("not supported - not needed by new ops");
+#else
// build (reverse ordered) list of the stack of snapshots, terminated with a NULL
Vector<const Snapshot*> snapshotList;
snapshotList.push(nullptr);
@@ -171,6 +174,7 @@
outTransform->multiply(*(current->transform));
}
}
+#endif
}
///////////////////////////////////////////////////////////////////////////////
@@ -223,15 +227,19 @@
}
void Snapshot::setProjectionPathMask(LinearAllocator& allocator, const SkPath* path) {
+#if HWUI_NEW_OPS
+ // TODO: remove allocator param for HWUI_NEW_OPS
+ projectionPathMask = path;
+#else
if (path) {
ProjectionPathMask* mask = new (allocator) ProjectionPathMask;
mask->projectionMask = path;
buildScreenSpaceTransform(&(mask->projectionMaskTransform));
-
projectionPathMask = mask;
} else {
projectionPathMask = nullptr;
}
+#endif
}
///////////////////////////////////////////////////////////////////////////////
diff --git a/libs/hwui/Snapshot.h b/libs/hwui/Snapshot.h
index b03643f..3a01d04 100644
--- a/libs/hwui/Snapshot.h
+++ b/libs/hwui/Snapshot.h
@@ -63,6 +63,7 @@
float radius;
};
+// TODO: remove for HWUI_NEW_OPS
class ProjectionPathMask {
public:
static void* operator new(size_t size) = delete;
@@ -219,6 +220,7 @@
* Fills outTransform with the current, total transform to screen space,
* across layer boundaries.
*/
+ // TODO: remove for HWUI_NEW_OPS
void buildScreenSpaceTransform(Matrix4* outTransform) const;
/**
@@ -294,9 +296,13 @@
const RoundRectClipState* roundRectClipState;
/**
- * Current projection masking path - used exclusively to mask tessellated circles.
+ * Current projection masking path - used exclusively to mask projected, tessellated circles.
*/
+#if HWUI_NEW_OPS
+ const SkPath* projectionPathMask;
+#else
const ProjectionPathMask* projectionPathMask;
+#endif
void dump() const;
diff --git a/libs/hwui/tests/unit/FrameBuilderTests.cpp b/libs/hwui/tests/unit/FrameBuilderTests.cpp
index f86898f..4c56a22 100644
--- a/libs/hwui/tests/unit/FrameBuilderTests.cpp
+++ b/libs/hwui/tests/unit/FrameBuilderTests.cpp
@@ -216,8 +216,7 @@
<< "Expect number of ops = 2 * loop count";
}
-// TODO: Disabled due to b/26793764
-TEST(FrameBuilder, DISABLED_clippedMerging) {
+TEST(FrameBuilder, clippedMerging) {
class ClippedMergingTestRenderer : public TestRendererBase {
public:
void onMergedBitmapOps(const MergedBakedOpList& opList) override {
@@ -990,21 +989,26 @@
EXPECT_EQ(Rect(100, 100), op.unmappedBounds);
EXPECT_EQ(SK_ColorWHITE, op.paint->getColor());
expectedMatrix.loadIdentity();
+ EXPECT_EQ(nullptr, state.computedState.localProjectionPathMask);
break;
case 1:
EXPECT_EQ(Rect(-10, -10, 60, 60), op.unmappedBounds);
EXPECT_EQ(SK_ColorDKGRAY, op.paint->getColor());
- expectedMatrix.loadTranslate(50, 50, 0); // TODO: should scroll be respected here?
+ expectedMatrix.loadTranslate(50 - scrollX, 50 - scrollY, 0);
+ ASSERT_NE(nullptr, state.computedState.localProjectionPathMask);
+ EXPECT_EQ(Rect(-35, -30, 45, 50),
+ Rect(state.computedState.localProjectionPathMask->getBounds()));
break;
case 2:
EXPECT_EQ(Rect(100, 50), op.unmappedBounds);
EXPECT_EQ(SK_ColorBLUE, op.paint->getColor());
expectedMatrix.loadTranslate(-scrollX, 50 - scrollY, 0);
+ EXPECT_EQ(nullptr, state.computedState.localProjectionPathMask);
break;
default:
ADD_FAILURE();
}
- EXPECT_MATRIX_APPROX_EQ(expectedMatrix, state.computedState.transform);
+ EXPECT_EQ(expectedMatrix, state.computedState.transform);
}
};
@@ -1045,6 +1049,9 @@
});
auto parent = TestUtils::createNode(0, 0, 100, 100,
[&receiverBackground, &child](RenderProperties& properties, RecordingCanvas& canvas) {
+ // Set a rect outline for the projecting ripple to be masked against.
+ properties.mutableOutline().setRoundRect(10, 10, 90, 90, 5, 1.0f);
+
canvas.save(SaveFlags::MatrixClip);
canvas.translate(-scrollX, -scrollY); // Apply scroll (note: bg undoes this internally)
canvas.drawRenderNode(receiverBackground.get());
@@ -1059,6 +1066,145 @@
EXPECT_EQ(3, renderer.getIndex());
}
+RENDERTHREAD_TEST(FrameBuilder, projectionHwLayer) {
+ static const int scrollX = 5;
+ static const int scrollY = 10;
+ class ProjectionHwLayerTestRenderer : public TestRendererBase {
+ public:
+ void startRepaintLayer(OffscreenBuffer* offscreenBuffer, const Rect& repaintRect) override {
+ EXPECT_EQ(0, mIndex++);
+ }
+ void onArcOp(const ArcOp& op, const BakedOpState& state) override {
+ EXPECT_EQ(1, mIndex++);
+ ASSERT_EQ(nullptr, state.computedState.localProjectionPathMask);
+ }
+ void endLayer() override {
+ EXPECT_EQ(2, mIndex++);
+ }
+ void onRectOp(const RectOp& op, const BakedOpState& state) override {
+ EXPECT_EQ(3, mIndex++);
+ ASSERT_EQ(nullptr, state.computedState.localProjectionPathMask);
+ }
+ void onOvalOp(const OvalOp& op, const BakedOpState& state) override {
+ EXPECT_EQ(4, mIndex++);
+ ASSERT_NE(nullptr, state.computedState.localProjectionPathMask);
+ Matrix4 expected;
+ expected.loadTranslate(100 - scrollX, 100 - scrollY, 0);
+ EXPECT_EQ(expected, state.computedState.transform);
+ EXPECT_EQ(Rect(-85, -80, 295, 300),
+ Rect(state.computedState.localProjectionPathMask->getBounds()));
+ }
+ void onLayerOp(const LayerOp& op, const BakedOpState& state) override {
+ EXPECT_EQ(5, mIndex++);
+ ASSERT_EQ(nullptr, state.computedState.localProjectionPathMask);
+ }
+ };
+ auto receiverBackground = TestUtils::createNode(0, 0, 400, 400,
+ [](RenderProperties& properties, RecordingCanvas& canvas) {
+ properties.setProjectionReceiver(true);
+ // scroll doesn't apply to background, so undone via translationX/Y
+ // NOTE: translationX/Y only! no other transform properties may be set for a proj receiver!
+ properties.setTranslationX(scrollX);
+ properties.setTranslationY(scrollY);
+
+ canvas.drawRect(0, 0, 400, 400, SkPaint());
+ });
+ auto projectingRipple = TestUtils::createNode(0, 0, 200, 200,
+ [](RenderProperties& properties, RecordingCanvas& canvas) {
+ properties.setProjectBackwards(true);
+ properties.setClipToBounds(false);
+ canvas.drawOval(100, 100, 300, 300, SkPaint()); // drawn mostly out of layer bounds
+ });
+ auto child = TestUtils::createNode(100, 100, 300, 300,
+ [&projectingRipple](RenderProperties& properties, RecordingCanvas& canvas) {
+ properties.mutateLayerProperties().setType(LayerType::RenderLayer);
+ canvas.drawRenderNode(projectingRipple.get());
+ canvas.drawArc(0, 0, 200, 200, 0.0f, 280.0f, true, SkPaint());
+ });
+ auto parent = TestUtils::createNode(0, 0, 400, 400,
+ [&receiverBackground, &child](RenderProperties& properties, RecordingCanvas& canvas) {
+ // Set a rect outline for the projecting ripple to be masked against.
+ properties.mutableOutline().setRoundRect(10, 10, 390, 390, 0, 1.0f);
+ canvas.translate(-scrollX, -scrollY); // Apply scroll (note: bg undoes this internally)
+ canvas.drawRenderNode(receiverBackground.get());
+ canvas.drawRenderNode(child.get());
+ });
+
+ OffscreenBuffer** layerHandle = child->getLayerHandle();
+
+ // create RenderNode's layer here in same way prepareTree would, setting windowTransform
+ OffscreenBuffer layer(renderThread.renderState(), Caches::getInstance(), 200, 200);
+ Matrix4 windowTransform;
+ windowTransform.loadTranslate(100, 100, 0); // total transform of layer's origin
+ layer.setWindowTransform(windowTransform);
+ *layerHandle = &layer;
+
+ auto syncedList = TestUtils::createSyncedNodeList(parent);
+ LayerUpdateQueue layerUpdateQueue; // Note: enqueue damage post-sync, so bounds are valid
+ layerUpdateQueue.enqueueLayerWithDamage(child.get(), Rect(200, 200));
+ FrameBuilder frameBuilder(layerUpdateQueue, SkRect::MakeWH(400, 400), 400, 400,
+ syncedList, sLightGeometry, nullptr);
+ ProjectionHwLayerTestRenderer renderer;
+ frameBuilder.replayBakedOps<TestDispatcher>(renderer);
+ EXPECT_EQ(6, renderer.getIndex());
+
+ // clean up layer pointer, so we can safely destruct RenderNode
+ *layerHandle = nullptr;
+}
+
+RENDERTHREAD_TEST(FrameBuilder, projectionChildScroll) {
+ static const int scrollX = 500000;
+ static const int scrollY = 0;
+ class ProjectionChildScrollTestRenderer : public TestRendererBase {
+ public:
+ void onRectOp(const RectOp& op, const BakedOpState& state) override {
+ EXPECT_EQ(0, mIndex++);
+ EXPECT_TRUE(state.computedState.transform.isIdentity());
+ }
+ void onOvalOp(const OvalOp& op, const BakedOpState& state) override {
+ EXPECT_EQ(1, mIndex++);
+ ASSERT_NE(nullptr, state.computedState.clipState);
+ ASSERT_EQ(ClipMode::Rectangle, state.computedState.clipState->mode);
+ ASSERT_EQ(Rect(400, 400), state.computedState.clipState->rect);
+ EXPECT_TRUE(state.computedState.transform.isIdentity());
+ }
+ };
+ auto receiverBackground = TestUtils::createNode(0, 0, 400, 400,
+ [](RenderProperties& properties, RecordingCanvas& canvas) {
+ properties.setProjectionReceiver(true);
+ canvas.drawRect(0, 0, 400, 400, SkPaint());
+ });
+ auto projectingRipple = TestUtils::createNode(0, 0, 200, 200,
+ [](RenderProperties& properties, RecordingCanvas& canvas) {
+ // scroll doesn't apply to background, so undone via translationX/Y
+ // NOTE: translationX/Y only! no other transform properties may be set for a proj receiver!
+ properties.setTranslationX(scrollX);
+ properties.setTranslationY(scrollY);
+ properties.setProjectBackwards(true);
+ properties.setClipToBounds(false);
+ canvas.drawOval(0, 0, 200, 200, SkPaint());
+ });
+ auto child = TestUtils::createNode(0, 0, 400, 400,
+ [&projectingRipple](RenderProperties& properties, RecordingCanvas& canvas) {
+ // Record time clip will be ignored by projectee
+ canvas.clipRect(100, 100, 300, 300, SkRegion::kIntersect_Op);
+
+ canvas.translate(-scrollX, -scrollY); // Apply scroll (note: bg undoes this internally)
+ canvas.drawRenderNode(projectingRipple.get());
+ });
+ auto parent = TestUtils::createNode(0, 0, 400, 400,
+ [&receiverBackground, &child](RenderProperties& properties, RecordingCanvas& canvas) {
+ canvas.drawRenderNode(receiverBackground.get());
+ canvas.drawRenderNode(child.get());
+ });
+
+ FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(400, 400), 400, 400,
+ TestUtils::createSyncedNodeList(parent), sLightGeometry, nullptr);
+ ProjectionChildScrollTestRenderer renderer;
+ frameBuilder.replayBakedOps<TestDispatcher>(renderer);
+ EXPECT_EQ(2, renderer.getIndex());
+}
+
// creates a 100x100 shadow casting node with provided translationZ
static sp<RenderNode> createWhiteRectShadowCaster(float translationZ) {
return TestUtils::createNode(0, 0, 100, 100,
diff --git a/location/java/android/location/GnssClock.java b/location/java/android/location/GnssClock.java
index 3c8a78d..6a7801e 100644
--- a/location/java/android/location/GnssClock.java
+++ b/location/java/android/location/GnssClock.java
@@ -26,26 +26,26 @@
public final class GnssClock implements Parcelable {
// The following enumerations must be in sync with the values declared in gps.h
- private static final short HAS_NO_FLAGS = 0;
- private static final short HAS_LEAP_SECOND = (1<<0);
- private static final short HAS_TIME_UNCERTAINTY = (1<<1);
- private static final short HAS_FULL_BIAS = (1<<2);
- private static final short HAS_BIAS = (1<<3);
- private static final short HAS_BIAS_UNCERTAINTY = (1<<4);
- private static final short HAS_DRIFT = (1<<5);
- private static final short HAS_DRIFT_UNCERTAINTY = (1<<6);
+ private static final int HAS_NO_FLAGS = 0;
+ private static final int HAS_LEAP_SECOND = (1<<0);
+ private static final int HAS_TIME_UNCERTAINTY = (1<<1);
+ private static final int HAS_FULL_BIAS = (1<<2);
+ private static final int HAS_BIAS = (1<<3);
+ private static final int HAS_BIAS_UNCERTAINTY = (1<<4);
+ private static final int HAS_DRIFT = (1<<5);
+ private static final int HAS_DRIFT_UNCERTAINTY = (1<<6);
// End enumerations in sync with gps.h
- private short mFlags;
- private short mLeapSecond;
- private long mTimeInNs;
- private double mTimeUncertaintyInNs;
- private long mFullBiasInNs;
- private double mBiasInNs;
- private double mBiasUncertaintyInNs;
- private double mDriftInNsPerSec;
- private double mDriftUncertaintyInNsPerSec;
+ private int mFlags;
+ private int mLeapSecond;
+ private long mTimeNanos;
+ private double mTimeUncertaintyNanos;
+ private long mFullBiasNanos;
+ private double mBiasNanos;
+ private double mBiasUncertaintyNanos;
+ private double mDriftNanosPerSecond;
+ private double mDriftUncertaintyNanosPerSecond;
private int mHardwareClockDiscontinuityCount;
GnssClock() {
@@ -58,13 +58,13 @@
public void set(GnssClock clock) {
mFlags = clock.mFlags;
mLeapSecond = clock.mLeapSecond;
- mTimeInNs = clock.mTimeInNs;
- mTimeUncertaintyInNs = clock.mTimeUncertaintyInNs;
- mFullBiasInNs = clock.mFullBiasInNs;
- mBiasInNs = clock.mBiasInNs;
- mBiasUncertaintyInNs = clock.mBiasUncertaintyInNs;
- mDriftInNsPerSec = clock.mDriftInNsPerSec;
- mDriftUncertaintyInNsPerSec = clock.mDriftUncertaintyInNsPerSec;
+ mTimeNanos = clock.mTimeNanos;
+ mTimeUncertaintyNanos = clock.mTimeUncertaintyNanos;
+ mFullBiasNanos = clock.mFullBiasNanos;
+ mBiasNanos = clock.mBiasNanos;
+ mBiasUncertaintyNanos = clock.mBiasUncertaintyNanos;
+ mDriftNanosPerSecond = clock.mDriftNanosPerSecond;
+ mDriftUncertaintyNanosPerSecond = clock.mDriftUncertaintyNanosPerSecond;
mHardwareClockDiscontinuityCount = clock.mHardwareClockDiscontinuityCount;
}
@@ -89,14 +89,14 @@
*
* The value is only available if {@link #hasLeapSecond()} is true.
*/
- public short getLeapSecond() {
+ public int getLeapSecond() {
return mLeapSecond;
}
/**
* Sets the leap second associated with the clock's time.
*/
- public void setLeapSecond(short leapSecond) {
+ public void setLeapSecond(int leapSecond) {
setFlag(HAS_LEAP_SECOND);
mLeapSecond = leapSecond;
}
@@ -106,7 +106,7 @@
*/
public void resetLeapSecond() {
resetFlag(HAS_LEAP_SECOND);
- mLeapSecond = Short.MIN_VALUE;
+ mLeapSecond = Integer.MIN_VALUE;
}
/**
@@ -114,30 +114,30 @@
*
* For 'local hardware clock' this value is expected to be monotonically increasing during the
* reporting session. The real GPS time can be derived by compensating
- * {@link #getFullBiasInNs()} (when it is available) from this value.
+ * {@link #getFullBiasNanos()} (when it is available) from this value.
*
* For 'GPS time' this value is expected to be the best estimation of current GPS time that GPS
- * receiver can achieve. {@link #getTimeUncertaintyInNs()} should be available when GPS time is
+ * receiver can achieve. {@link #getTimeUncertaintyNanos()} should be available when GPS time is
* specified.
*
- * Sub-nanosecond accuracy can be provided by means of {@link #getBiasInNs()}.
- * The reported time includes {@link #getTimeUncertaintyInNs()}.
+ * Sub-nanosecond accuracy can be provided by means of {@link #getBiasNanos()}.
+ * The reported time includes {@link #getTimeUncertaintyNanos()}.
*/
- public long getTimeInNs() {
- return mTimeInNs;
+ public long getTimeNanos() {
+ return mTimeNanos;
}
/**
- * Sets the GPS receiver internal clock in nanoseconds.
+ * Sets the GNSS receiver internal clock in nanoseconds.
*/
- public void setTimeInNs(long timeInNs) {
- mTimeInNs = timeInNs;
+ public void setTimeNanos(long timeNanos) {
+ mTimeNanos = timeNanos;
}
/**
- * Returns true if {@link #getTimeUncertaintyInNs()} is available, false otherwise.
+ * Returns true if {@link #getTimeUncertaintyNanos()} is available, false otherwise.
*/
- public boolean hasTimeUncertaintyInNs() {
+ public boolean hasTimeUncertaintyNanos() {
return isFlagSet(HAS_TIME_UNCERTAINTY);
}
@@ -145,189 +145,189 @@
* Gets the clock's time Uncertainty (1-Sigma) in nanoseconds.
* The uncertainty is represented as an absolute (single sided) value.
*
- * The value is only available if {@link #hasTimeUncertaintyInNs()} is true.
+ * The value is only available if {@link #hasTimeUncertaintyNanos()} is true.
*/
- public double getTimeUncertaintyInNs() {
- return mTimeUncertaintyInNs;
+ public double getTimeUncertaintyNanos() {
+ return mTimeUncertaintyNanos;
}
/**
* Sets the clock's Time Uncertainty (1-Sigma) in nanoseconds.
*/
- public void setTimeUncertaintyInNs(double timeUncertaintyInNs) {
+ public void setTimeUncertaintyNanos(double timeUncertaintyNanos) {
setFlag(HAS_TIME_UNCERTAINTY);
- mTimeUncertaintyInNs = timeUncertaintyInNs;
+ mTimeUncertaintyNanos = timeUncertaintyNanos;
}
/**
* Resets the clock's Time Uncertainty (1-Sigma) in nanoseconds.
*/
- public void resetTimeUncertaintyInNs() {
+ public void resetTimeUncertaintyNanos() {
resetFlag(HAS_TIME_UNCERTAINTY);
- mTimeUncertaintyInNs = Double.NaN;
+ mTimeUncertaintyNanos = Double.NaN;
}
/**
- * Returns true if {@link #getFullBiasInNs()} is available, false otherwise.
+ * Returns true if {@link #getFullBiasNanos()} is available, false otherwise.
*/
- public boolean hasFullBiasInNs() {
+ public boolean hasFullBiasNanos() {
return isFlagSet(HAS_FULL_BIAS);
}
/**
- * Gets the difference between hardware clock ({@link #getTimeInNs()}) inside GPS receiver and
+ * Gets the difference between hardware clock ({@link #getTimeNanos()}) inside GPS receiver and
* the true GPS time since 0000Z, January 6, 1980, in nanoseconds.
*
* This value is available if the receiver has estimated GPS time. If the computed time is for a
* non-GPS constellation, the time offset of that constellation to GPS has to be applied to fill
- * this value. The value contains the 'bias uncertainty' {@link #getBiasUncertaintyInNs()} in
+ * this value. The value contains the 'bias uncertainty' {@link #getBiasUncertaintyNanos()} in
* it, and it should be used for quality check. The value is only available if
- * {@link #hasFullBiasInNs()} is true.
+ * {@link #hasFullBiasNanos()} is true.
*
* The sign of the value is defined by the following equation:
* local estimate of GPS time = time_ns + (full_bias_ns + bias_ns)
*/
- public long getFullBiasInNs() {
- return mFullBiasInNs;
+ public long getFullBiasNanos() {
+ return mFullBiasNanos;
}
/**
* Sets the full bias in nanoseconds.
*/
- public void setFullBiasInNs(long value) {
+ public void setFullBiasNanos(long value) {
setFlag(HAS_FULL_BIAS);
- mFullBiasInNs = value;
+ mFullBiasNanos = value;
}
/**
* Resets the full bias in nanoseconds.
*/
- public void resetFullBiasInNs() {
+ public void resetFullBiasNanos() {
resetFlag(HAS_FULL_BIAS);
- mFullBiasInNs = Long.MIN_VALUE;
+ mFullBiasNanos = Long.MIN_VALUE;
}
/**
- * Returns true if {@link #getBiasInNs()} is available, false otherwise.
+ * Returns true if {@link #getBiasNanos()} is available, false otherwise.
*/
- public boolean hasBiasInNs() {
+ public boolean hasBiasNanos() {
return isFlagSet(HAS_BIAS);
}
/**
* Gets the clock's sub-nanosecond bias.
- * The reported bias includes {@link #getBiasUncertaintyInNs()}.
+ * The reported bias includes {@link #getBiasUncertaintyNanos()}.
*
- * The value is only available if {@link #hasBiasInNs()} is true.
+ * The value is only available if {@link #hasBiasNanos()} is true.
*/
- public double getBiasInNs() {
- return mBiasInNs;
+ public double getBiasNanos() {
+ return mBiasNanos;
}
/**
* Sets the sub-nanosecond bias.
*/
- public void setBiasInNs(double biasInNs) {
+ public void setBiasNanos(double biasNanos) {
setFlag(HAS_BIAS);
- mBiasInNs = biasInNs;
+ mBiasNanos = biasNanos;
}
/**
* Resets the clock's Bias in nanoseconds.
*/
- public void resetBiasInNs() {
+ public void resetBiasNanos() {
resetFlag(HAS_BIAS);
- mBiasInNs = Double.NaN;
+ mBiasNanos = Double.NaN;
}
/**
- * Returns true if {@link #getBiasUncertaintyInNs()} is available, false otherwise.
+ * Returns true if {@link #getBiasUncertaintyNanos()} is available, false otherwise.
*/
- public boolean hasBiasUncertaintyInNs() {
+ public boolean hasBiasUncertaintyNanos() {
return isFlagSet(HAS_BIAS_UNCERTAINTY);
}
/**
* Gets the clock's Bias Uncertainty (1-Sigma) in nanoseconds.
*
- * The value is only available if {@link #hasBiasUncertaintyInNs()} is true.
+ * The value is only available if {@link #hasBiasUncertaintyNanos()} is true.
*/
- public double getBiasUncertaintyInNs() {
- return mBiasUncertaintyInNs;
+ public double getBiasUncertaintyNanos() {
+ return mBiasUncertaintyNanos;
}
/**
* Sets the clock's Bias Uncertainty (1-Sigma) in nanoseconds.
*/
- public void setBiasUncertaintyInNs(double biasUncertaintyInNs) {
+ public void setBiasUncertaintyNanos(double biasUncertaintyNanos) {
setFlag(HAS_BIAS_UNCERTAINTY);
- mBiasUncertaintyInNs = biasUncertaintyInNs;
+ mBiasUncertaintyNanos = biasUncertaintyNanos;
}
/**
* Resets the clock's Bias Uncertainty (1-Sigma) in nanoseconds.
*/
- public void resetBiasUncertaintyInNs() {
+ public void resetBiasUncertaintyNanos() {
resetFlag(HAS_BIAS_UNCERTAINTY);
- mBiasUncertaintyInNs = Double.NaN;
+ mBiasUncertaintyNanos = Double.NaN;
}
/**
- * Returns true if {@link #getDriftInNsPerSec()} is available, false otherwise.
+ * Returns true if {@link #getDriftNanosPerSecond()} is available, false otherwise.
*/
- public boolean hasDriftInNsPerSec() {
+ public boolean hasDriftNanosPerSecond() {
return isFlagSet(HAS_DRIFT);
}
/**
* Gets the clock's Drift in nanoseconds per second.
* A positive value indicates that the frequency is higher than the nominal frequency.
- * The reported drift includes {@link #getDriftUncertaintyInNsPerSec()}.
+ * The reported drift includes {@link #getDriftUncertaintyNanosPerSecond()}.
*
- * The value is only available if {@link #hasDriftInNsPerSec()} is true.
+ * The value is only available if {@link #hasDriftNanosPerSecond()} is true.
*/
- public double getDriftInNsPerSec() {
- return mDriftInNsPerSec;
+ public double getDriftNanosPerSecond() {
+ return mDriftNanosPerSecond;
}
/**
* Sets the clock's Drift in nanoseconds per second.
*/
- public void setDriftInNsPerSec(double driftInNsPerSec) {
+ public void setDriftNanosPerSecond(double driftNanosPerSecond) {
setFlag(HAS_DRIFT);
- mDriftInNsPerSec = driftInNsPerSec;
+ mDriftNanosPerSecond = driftNanosPerSecond;
}
/**
* Resets the clock's Drift in nanoseconds per second.
*/
- public void resetDriftInNsPerSec() {
+ public void resetDriftNanosPerSecond() {
resetFlag(HAS_DRIFT);
- mDriftInNsPerSec = Double.NaN;
+ mDriftNanosPerSecond = Double.NaN;
}
/**
- * Returns true if {@link #getDriftUncertaintyInNsPerSec()} is available, false otherwise.
+ * Returns true if {@link #getDriftUncertaintyNanosPerSecond()} is available, false otherwise.
*/
- public boolean hasDriftUncertaintyInNsPerSec() {
+ public boolean hasDriftUncertaintyNanosPerSecond() {
return isFlagSet(HAS_DRIFT_UNCERTAINTY);
}
/**
* Gets the clock's Drift Uncertainty (1-Sigma) in nanoseconds per second.
*
- * The value is only available if {@link #hasDriftUncertaintyInNsPerSec()} is true.
+ * The value is only available if {@link #hasDriftUncertaintyNanosPerSecond()} is true.
*/
- public double getDriftUncertaintyInNsPerSec() {
- return mDriftUncertaintyInNsPerSec;
+ public double getDriftUncertaintyNanosPerSecond() {
+ return mDriftUncertaintyNanosPerSecond;
}
/**
* Sets the clock's Drift Uncertainty (1-Sigma) in nanoseconds per second.
*/
- public void setDriftUncertaintyInNsPerSec(double driftUncertaintyInNsPerSec) {
+ public void setDriftUncertaintyNanosPerSecond(double driftUncertaintyNanosPerSecond) {
setFlag(HAS_DRIFT_UNCERTAINTY);
- mDriftUncertaintyInNsPerSec = driftUncertaintyInNsPerSec;
+ mDriftUncertaintyNanosPerSecond = driftUncertaintyNanosPerSecond;
}
/**
@@ -347,9 +347,9 @@
/**
* Resets the clock's Drift Uncertainty (1-Sigma) in nanoseconds per second.
*/
- public void resetDriftUncertaintyInNsPerSec() {
+ public void resetDriftUncertaintyNanosPerSecond() {
resetFlag(HAS_DRIFT_UNCERTAINTY);
- mDriftUncertaintyInNsPerSec = Double.NaN;
+ mDriftUncertaintyNanosPerSecond = Double.NaN;
}
public static final Creator<GnssClock> CREATOR = new Creator<GnssClock>() {
@@ -357,15 +357,15 @@
public GnssClock createFromParcel(Parcel parcel) {
GnssClock gpsClock = new GnssClock();
- gpsClock.mFlags = (short) parcel.readInt();
- gpsClock.mLeapSecond = (short) parcel.readInt();
- gpsClock.mTimeInNs = parcel.readLong();
- gpsClock.mTimeUncertaintyInNs = parcel.readDouble();
- gpsClock.mFullBiasInNs = parcel.readLong();
- gpsClock.mBiasInNs = parcel.readDouble();
- gpsClock.mBiasUncertaintyInNs = parcel.readDouble();
- gpsClock.mDriftInNsPerSec = parcel.readDouble();
- gpsClock.mDriftUncertaintyInNsPerSec = parcel.readDouble();
+ gpsClock.mFlags = parcel.readInt();
+ gpsClock.mLeapSecond = parcel.readInt();
+ gpsClock.mTimeNanos = parcel.readLong();
+ gpsClock.mTimeUncertaintyNanos = parcel.readDouble();
+ gpsClock.mFullBiasNanos = parcel.readLong();
+ gpsClock.mBiasNanos = parcel.readDouble();
+ gpsClock.mBiasUncertaintyNanos = parcel.readDouble();
+ gpsClock.mDriftNanosPerSecond = parcel.readDouble();
+ gpsClock.mDriftUncertaintyNanosPerSecond = parcel.readDouble();
gpsClock.mHardwareClockDiscontinuityCount = parcel.readInt();
return gpsClock;
@@ -381,13 +381,13 @@
public void writeToParcel(Parcel parcel, int flags) {
parcel.writeInt(mFlags);
parcel.writeInt(mLeapSecond);
- parcel.writeLong(mTimeInNs);
- parcel.writeDouble(mTimeUncertaintyInNs);
- parcel.writeLong(mFullBiasInNs);
- parcel.writeDouble(mBiasInNs);
- parcel.writeDouble(mBiasUncertaintyInNs);
- parcel.writeDouble(mDriftInNsPerSec);
- parcel.writeDouble(mDriftUncertaintyInNsPerSec);
+ parcel.writeLong(mTimeNanos);
+ parcel.writeDouble(mTimeUncertaintyNanos);
+ parcel.writeLong(mFullBiasNanos);
+ parcel.writeDouble(mBiasNanos);
+ parcel.writeDouble(mBiasUncertaintyNanos);
+ parcel.writeDouble(mDriftNanosPerSecond);
+ parcel.writeDouble(mDriftUncertaintyNanosPerSecond);
parcel.writeInt(mHardwareClockDiscontinuityCount);
}
@@ -406,29 +406,29 @@
builder.append(String.format(
formatWithUncertainty,
- "TimeInNs",
- mTimeInNs,
- "TimeUncertaintyInNs",
- hasTimeUncertaintyInNs() ? mTimeUncertaintyInNs : null));
+ "TimeNanos",
+ mTimeNanos,
+ "TimeUncertaintyNanos",
+ hasTimeUncertaintyNanos() ? mTimeUncertaintyNanos : null));
builder.append(String.format(
format,
- "FullBiasInNs",
- hasFullBiasInNs() ? mFullBiasInNs : null));
+ "FullBiasNanos",
+ hasFullBiasNanos() ? mFullBiasNanos : null));
builder.append(String.format(
formatWithUncertainty,
- "BiasInNs",
- hasBiasInNs() ? mBiasInNs : null,
- "BiasUncertaintyInNs",
- hasBiasUncertaintyInNs() ? mBiasUncertaintyInNs : null));
+ "BiasNanos",
+ hasBiasNanos() ? mBiasNanos : null,
+ "BiasUncertaintyNanos",
+ hasBiasUncertaintyNanos() ? mBiasUncertaintyNanos : null));
builder.append(String.format(
formatWithUncertainty,
- "DriftInNsPerSec",
- hasDriftInNsPerSec() ? mDriftInNsPerSec : null,
- "DriftUncertaintyInNsPerSec",
- hasDriftUncertaintyInNsPerSec() ? mDriftUncertaintyInNsPerSec : null));
+ "DriftNanosPerSecond",
+ hasDriftNanosPerSecond() ? mDriftNanosPerSecond : null,
+ "DriftUncertaintyNanosPerSecond",
+ hasDriftUncertaintyNanosPerSecond() ? mDriftUncertaintyNanosPerSecond : null));
return builder.toString();
}
@@ -436,25 +436,25 @@
private void initialize() {
mFlags = HAS_NO_FLAGS;
resetLeapSecond();
- setTimeInNs(Long.MIN_VALUE);
- resetTimeUncertaintyInNs();
- resetFullBiasInNs();
- resetBiasInNs();
- resetBiasUncertaintyInNs();
- resetDriftInNsPerSec();
- resetDriftUncertaintyInNsPerSec();
+ setTimeNanos(Long.MIN_VALUE);
+ resetTimeUncertaintyNanos();
+ resetFullBiasNanos();
+ resetBiasNanos();
+ resetBiasUncertaintyNanos();
+ resetDriftNanosPerSecond();
+ resetDriftUncertaintyNanosPerSecond();
setHardwareClockDiscontinuityCount(Integer.MIN_VALUE);
}
- private void setFlag(short flag) {
+ private void setFlag(int flag) {
mFlags |= flag;
}
- private void resetFlag(short flag) {
+ private void resetFlag(int flag) {
mFlags &= ~flag;
}
- private boolean isFlagSet(short flag) {
+ private boolean isFlagSet(int flag) {
return (mFlags & flag) == flag;
}
}
diff --git a/location/java/android/location/GnssMeasurement.java b/location/java/android/location/GnssMeasurement.java
index abdc13c..367c52f 100644
--- a/location/java/android/location/GnssMeasurement.java
+++ b/location/java/android/location/GnssMeasurement.java
@@ -28,82 +28,35 @@
*/
public final class GnssMeasurement implements Parcelable {
private int mFlags;
- private short mSvid;
- private byte mConstellationType;
- private double mTimeOffsetInNs;
- private short mState;
- private long mReceivedSvTimeInNs;
- private long mReceivedSvTimeUncertaintyInNs;
- private double mCn0InDbHz;
- private double mPseudorangeRateInMetersPerSec;
- private double mPseudorangeRateUncertaintyInMetersPerSec;
- private short mAccumulatedDeltaRangeState;
- private double mAccumulatedDeltaRangeInMeters;
- private double mAccumulatedDeltaRangeUncertaintyInMeters;
- private double mPseudorangeInMeters;
- private double mPseudorangeUncertaintyInMeters;
- private double mCodePhaseInChips;
- private double mCodePhaseUncertaintyInChips;
- private float mCarrierFrequencyInHz;
+ private int mSvid;
+ private int mConstellationType;
+ private double mTimeOffsetNanos;
+ private int mState;
+ private long mReceivedSvTimeNanos;
+ private long mReceivedSvTimeUncertaintyNanos;
+ private double mCn0DbHz;
+ private double mPseudorangeRateMetersPerSecond;
+ private double mPseudorangeRateUncertaintyMetersPerSecond;
+ private int mAccumulatedDeltaRangeState;
+ private double mAccumulatedDeltaRangeMeters;
+ private double mAccumulatedDeltaRangeUncertaintyMeters;
+ private float mCarrierFrequencyHz;
private long mCarrierCycles;
private double mCarrierPhase;
private double mCarrierPhaseUncertainty;
- private byte mLossOfLock;
- private int mBitNumber;
- private short mTimeFromLastBitInMs;
- private double mDopplerShiftInHz;
- private double mDopplerShiftUncertaintyInHz;
- private byte mMultipathIndicator;
+ private int mMultipathIndicator;
private double mSnrInDb;
- private double mElevationInDeg;
- private double mElevationUncertaintyInDeg;
- private double mAzimuthInDeg;
- private double mAzimuthUncertaintyInDeg;
- private boolean mUsedInFix;
// The following enumerations must be in sync with the values declared in gps.h
private static final int HAS_NO_FLAGS = 0;
private static final int HAS_SNR = (1<<0);
- private static final int HAS_ELEVATION = (1<<1);
- private static final int HAS_ELEVATION_UNCERTAINTY = (1<<2);
- private static final int HAS_AZIMUTH = (1<<3);
- private static final int HAS_AZIMUTH_UNCERTAINTY = (1<<4);
- private static final int HAS_PSEUDORANGE = (1<<5);
- private static final int HAS_PSEUDORANGE_UNCERTAINTY = (1<<6);
- private static final int HAS_CODE_PHASE = (1<<7);
- private static final int HAS_CODE_PHASE_UNCERTAINTY = (1<<8);
private static final int HAS_CARRIER_FREQUENCY = (1<<9);
private static final int HAS_CARRIER_CYCLES = (1<<10);
private static final int HAS_CARRIER_PHASE = (1<<11);
private static final int HAS_CARRIER_PHASE_UNCERTAINTY = (1<<12);
- private static final int HAS_BIT_NUMBER = (1<<13);
- private static final int HAS_TIME_FROM_LAST_BIT = (1<<14);
- private static final int HAS_DOPPLER_SHIFT = (1<<15);
- private static final int HAS_DOPPLER_SHIFT_UNCERTAINTY = (1<<16);
- // private static final int HAS_USED_IN_FIX = (1<<17);
private static final int HAS_UNCORRECTED_PSEUDORANGE_RATE = (1<<18);
- /** The status of 'loss of lock'. */
- @Retention(RetentionPolicy.SOURCE)
- @IntDef({LOSS_OF_LOCK_UNKNOWN, LOSS_OF_LOCK_OK, LOSS_OF_LOCK_CYCLE_SLIP})
- public @interface LossOfLockStatus {}
-
- /**
- * The indicator is not available or it is unknown.
- */
- public static final byte LOSS_OF_LOCK_UNKNOWN = 0;
-
- /**
- * The measurement does not present any indication of 'loss of lock'.
- */
- public static final byte LOSS_OF_LOCK_OK = 1;
-
- /**
- * 'Loss of lock' detected between the previous and current observation: cycle slip possible.
- */
- public static final byte LOSS_OF_LOCK_CYCLE_SLIP = 2;
-
/** The status of multipath. */
@Retention(RetentionPolicy.SOURCE)
@IntDef({MULTIPATH_INDICATOR_UNKNOWN, MULTIPATH_INDICATOR_DETECTED,
@@ -113,78 +66,78 @@
/**
* The indicator is not available or it is unknown.
*/
- public static final byte MULTIPATH_INDICATOR_UNKNOWN = 0;
+ public static final int MULTIPATH_INDICATOR_UNKNOWN = 0;
/**
* The measurement has been indicated to use multi-path.
*/
- public static final byte MULTIPATH_INDICATOR_DETECTED = 1;
+ public static final int MULTIPATH_INDICATOR_DETECTED = 1;
/**
* The measurement has been indicated not tu use multi-path.
*/
- public static final byte MULTIPATH_INDICATOR_NOT_USED = 2;
+ public static final int MULTIPATH_INDICATOR_NOT_USED = 2;
/**
* The state of GNSS receiver the measurement is invalid or unknown.
*/
- public static final short STATE_UNKNOWN = 0;
+ public static final int STATE_UNKNOWN = 0;
/**
* The state of the GNSS receiver is ranging code lock.
*/
- public static final short STATE_CODE_LOCK = (1<<0);
+ public static final int STATE_CODE_LOCK = (1<<0);
/**
* The state of the GNSS receiver is in bit sync.
*/
- public static final short STATE_BIT_SYNC = (1<<1);
+ public static final int STATE_BIT_SYNC = (1<<1);
/**
*The state of the GNSS receiver is in sub-frame sync.
*/
- public static final short STATE_SUBFRAME_SYNC = (1<<2);
+ public static final int STATE_SUBFRAME_SYNC = (1<<2);
/**
* The state of the GNSS receiver has TOW decoded.
*/
- public static final short STATE_TOW_DECODED = (1<<3);
+ public static final int STATE_TOW_DECODED = (1<<3);
/**
* The state of the GNSS receiver contains millisecond ambiguity.
*/
- public static final short STATE_MSEC_AMBIGUOUS = (1<<4);
+ public static final int STATE_MSEC_AMBIGUOUS = (1<<4);
/**
* All the GNSS receiver state flags.
*/
- private static final short STATE_ALL = STATE_CODE_LOCK | STATE_BIT_SYNC | STATE_SUBFRAME_SYNC
+ private static final int STATE_ALL = STATE_CODE_LOCK | STATE_BIT_SYNC | STATE_SUBFRAME_SYNC
| STATE_TOW_DECODED | STATE_MSEC_AMBIGUOUS;
/**
* The state of the 'Accumulated Delta Range' is invalid or unknown.
*/
- public static final short ADR_STATE_UNKNOWN = 0;
+ public static final int ADR_STATE_UNKNOWN = 0;
/**
* The state of the 'Accumulated Delta Range' is valid.
*/
- public static final short ADR_STATE_VALID = (1<<0);
+ public static final int ADR_STATE_VALID = (1<<0);
/**
* The state of the 'Accumulated Delta Range' has detected a reset.
*/
- public static final short ADR_STATE_RESET = (1<<1);
+ public static final int ADR_STATE_RESET = (1<<1);
/**
* The state of the 'Accumulated Delta Range' has a cycle slip detected.
*/
- public static final short ADR_STATE_CYCLE_SLIP = (1<<2);
+ public static final int ADR_STATE_CYCLE_SLIP = (1<<2);
/**
* All the 'Accumulated Delta Range' flags.
*/
- private static final short ADR_ALL = ADR_STATE_VALID | ADR_STATE_RESET | ADR_STATE_CYCLE_SLIP;
+ private static final int ADR_ALL = ADR_STATE_VALID | ADR_STATE_RESET | ADR_STATE_CYCLE_SLIP;
// End enumerations in sync with gps.h
@@ -199,38 +152,24 @@
mFlags = measurement.mFlags;
mSvid = measurement.mSvid;
mConstellationType = measurement.mConstellationType;
- mTimeOffsetInNs = measurement.mTimeOffsetInNs;
+ mTimeOffsetNanos = measurement.mTimeOffsetNanos;
mState = measurement.mState;
- mReceivedSvTimeInNs = measurement.mReceivedSvTimeInNs;
- mReceivedSvTimeUncertaintyInNs = measurement.mReceivedSvTimeUncertaintyInNs;
- mCn0InDbHz = measurement.mCn0InDbHz;
- mPseudorangeRateInMetersPerSec = measurement.mPseudorangeRateInMetersPerSec;
- mPseudorangeRateUncertaintyInMetersPerSec =
- measurement.mPseudorangeRateUncertaintyInMetersPerSec;
+ mReceivedSvTimeNanos = measurement.mReceivedSvTimeNanos;
+ mReceivedSvTimeUncertaintyNanos = measurement.mReceivedSvTimeUncertaintyNanos;
+ mCn0DbHz = measurement.mCn0DbHz;
+ mPseudorangeRateMetersPerSecond = measurement.mPseudorangeRateMetersPerSecond;
+ mPseudorangeRateUncertaintyMetersPerSecond =
+ measurement.mPseudorangeRateUncertaintyMetersPerSecond;
mAccumulatedDeltaRangeState = measurement.mAccumulatedDeltaRangeState;
- mAccumulatedDeltaRangeInMeters = measurement.mAccumulatedDeltaRangeInMeters;
- mAccumulatedDeltaRangeUncertaintyInMeters =
- measurement.mAccumulatedDeltaRangeUncertaintyInMeters;
- mPseudorangeInMeters = measurement.mPseudorangeInMeters;
- mPseudorangeUncertaintyInMeters = measurement.mPseudorangeUncertaintyInMeters;
- mCodePhaseInChips = measurement.mCodePhaseInChips;
- mCodePhaseUncertaintyInChips = measurement.mCodePhaseUncertaintyInChips;
- mCarrierFrequencyInHz = measurement.mCarrierFrequencyInHz;
+ mAccumulatedDeltaRangeMeters = measurement.mAccumulatedDeltaRangeMeters;
+ mAccumulatedDeltaRangeUncertaintyMeters =
+ measurement.mAccumulatedDeltaRangeUncertaintyMeters;
+ mCarrierFrequencyHz = measurement.mCarrierFrequencyHz;
mCarrierCycles = measurement.mCarrierCycles;
mCarrierPhase = measurement.mCarrierPhase;
mCarrierPhaseUncertainty = measurement.mCarrierPhaseUncertainty;
- mLossOfLock = measurement.mLossOfLock;
- mBitNumber = measurement.mBitNumber;
- mTimeFromLastBitInMs = measurement.mTimeFromLastBitInMs;
- mDopplerShiftInHz = measurement.mDopplerShiftInHz;
- mDopplerShiftUncertaintyInHz = measurement.mDopplerShiftUncertaintyInHz;
mMultipathIndicator = measurement.mMultipathIndicator;
mSnrInDb = measurement.mSnrInDb;
- mElevationInDeg = measurement.mElevationInDeg;
- mElevationUncertaintyInDeg = measurement.mElevationUncertaintyInDeg;
- mAzimuthInDeg = measurement.mAzimuthInDeg;
- mAzimuthUncertaintyInDeg = measurement.mAzimuthUncertaintyInDeg;
- mUsedInFix = measurement.mUsedInFix;
}
/**
@@ -244,14 +183,14 @@
* Gets the Pseudo-random number (PRN).
* Range: [1, 32]
*/
- public short getSvid() {
+ public int getSvid() {
return mSvid;
}
/**
* Sets the Pseud-random number (PRN).
*/
- public void setSvid(short value) {
+ public void setSvid(int value) {
mSvid = value;
}
@@ -259,14 +198,14 @@
* Getst the constellation type.
*/
@GnssStatus.ConstellationType
- public byte getConstellationType() {
+ public int getConstellationType() {
return mConstellationType;
}
/**
* Sets the constellation type.
*/
- public void setConstellationType(@GnssStatus.ConstellationType byte value) {
+ public void setConstellationType(@GnssStatus.ConstellationType int value) {
mConstellationType = value;
}
@@ -274,7 +213,7 @@
* Gets the time offset at which the measurement was taken in nanoseconds.
*
* The reference receiver's time from which this is offset is specified by
- * {@link GnssClock#getTimeInNs()}.
+ * {@link GnssClock#getTimeNanos()}.
*
* The sign of this value is given by the following equation:
* measurement time = time_ns + time_offset_ns
@@ -282,31 +221,31 @@
* The value provides an individual time-stamp for the measurement, and allows sub-nanosecond
* accuracy.
*/
- public double getTimeOffsetInNs() {
- return mTimeOffsetInNs;
+ public double getTimeOffsetNanos() {
+ return mTimeOffsetNanos;
}
/**
* Sets the time offset at which the measurement was taken in nanoseconds.
*/
- public void setTimeOffsetInNs(double value) {
- mTimeOffsetInNs = value;
+ public void setTimeOffsetNanos(double value) {
+ mTimeOffsetNanos = value;
}
/**
* Gets per-satellite sync state.
* It represents the current sync state for the associated satellite.
*
- * This value helps interpret {@link #getReceivedSvTimeInNs()}.
+ * This value helps interpret {@link #getReceivedSvTimeNanos()}.
*/
- public short getState() {
+ public int getState() {
return mState;
}
/**
* Sets the sync state.
*/
- public void setState(short value) {
+ public void setState(int value) {
mState = value;
}
@@ -408,29 +347,29 @@
* Symbol sync : [ 0 2ms ] : STATE_SYMBOL_SYNC is set
* Message : [ 0 1s ] : STATE_SBAS_SYNC is set
*/
- public long getReceivedSvTimeInNs() {
- return mReceivedSvTimeInNs;
+ public long getReceivedSvTimeNanos() {
+ return mReceivedSvTimeNanos;
}
/**
* Sets the received GNSS time in nanoseconds.
*/
- public void setReceivedSvTimeInNs(long value) {
- mReceivedSvTimeInNs = value;
+ public void setReceivedSvTimeNanos(long value) {
+ mReceivedSvTimeNanos = value;
}
/**
* Gets the received GNSS time uncertainty (1-Sigma) in nanoseconds.
*/
- public long getReceivedSvTimeUncertaintyInNs() {
- return mReceivedSvTimeUncertaintyInNs;
+ public long getReceivedSvTimeUncertaintyNanos() {
+ return mReceivedSvTimeUncertaintyNanos;
}
/**
* Sets the received GNSS time uncertainty (1-Sigma) in nanoseconds.
*/
- public void setReceivedSvTimeUncertaintyInNs(long value) {
- mReceivedSvTimeUncertaintyInNs = value;
+ public void setReceivedSvTimeUncertaintyNanos(long value) {
+ mReceivedSvTimeUncertaintyNanos = value;
}
/**
@@ -439,45 +378,46 @@
*
* The value contains the measured C/N0 for the signal at the antenna input.
*/
- public double getCn0InDbHz() {
- return mCn0InDbHz;
+ public double getCn0DbHz() {
+ return mCn0DbHz;
}
/**
* Sets the carrier-to-noise density in dB-Hz.
*/
- public void setCn0InDbHz(double value) {
- mCn0InDbHz = value;
+ public void setCn0DbHz(double value) {
+ mCn0DbHz = value;
}
/**
* Gets the Pseudorange rate at the timestamp in m/s.
- * The reported value includes {@link #getPseudorangeRateUncertaintyInMetersPerSec()}.
*
- * The correction of a given Pseudorange Rate value includes corrections from receiver and
- * satellite clock frequency errors.
- * {@link #isPseudorangeRateCorrected()} identifies the type of value reported.
+ * The reported value includes {@link #getPseudorangeRateUncertaintyMetersPerSecond()}.
*
- * A positive 'uncorrected' value indicates that the SV is moving away from the receiver.
- * The sign of the 'uncorrected' Pseudorange Rate and its relation to the sign of
- * {@link #getDopplerShiftInHz()} is given by the equation:
+ * The value is uncorrected, hence corrections for receiver and satellite clock frequency errors
+ * should not be included.
+ *
+ * A positive 'uncorrected' value indicates that the SV is moving away from the receiver. The
+ * sign of the 'uncorrected' 'pseudorange rate' and its relation to the sign of 'doppler shift'
+ * is given by the equation:
+ *
* pseudorange rate = -k * doppler shift (where k is a constant)
*/
- public double getPseudorangeRateInMetersPerSec() {
- return mPseudorangeRateInMetersPerSec;
+ public double getPseudorangeRateMetersPerSecond() {
+ return mPseudorangeRateMetersPerSecond;
}
/**
* Sets the pseudorange rate at the timestamp in m/s.
*/
- public void setPseudorangeRateInMetersPerSec(double value) {
- mPseudorangeRateInMetersPerSec = value;
+ public void setPseudorangeRateMetersPerSecond(double value) {
+ mPseudorangeRateMetersPerSecond = value;
}
/**
- * See {@link #getPseudorangeRateInMetersPerSec()} for more details.
+ * See {@link #getPseudorangeRateMetersPerSecond()} for more details.
*
- * @return {@code true} if {@link #getPseudorangeRateInMetersPerSec()} contains a corrected
+ * @return {@code true} if {@link #getPseudorangeRateMetersPerSecond()} contains a corrected
* value, {@code false} if it contains an uncorrected value.
*/
public boolean isPseudorangeRateCorrected() {
@@ -488,30 +428,30 @@
* Gets the pseudorange's rate uncertainty (1-Sigma) in m/s.
* The uncertainty is represented as an absolute (single sided) value.
*/
- public double getPseudorangeRateUncertaintyInMetersPerSec() {
- return mPseudorangeRateUncertaintyInMetersPerSec;
+ public double getPseudorangeRateUncertaintyMetersPerSecond() {
+ return mPseudorangeRateUncertaintyMetersPerSecond;
}
/**
* Sets the pseudorange's rate uncertainty (1-Sigma) in m/s.
*/
- public void setPseudorangeRateUncertaintyInMetersPerSec(double value) {
- mPseudorangeRateUncertaintyInMetersPerSec = value;
+ public void setPseudorangeRateUncertaintyMetersPerSecond(double value) {
+ mPseudorangeRateUncertaintyMetersPerSecond = value;
}
/**
* Gets 'Accumulated Delta Range' state.
- * It indicates whether {@link #getAccumulatedDeltaRangeInMeters()} is reset or there is a
+ * It indicates whether {@link #getAccumulatedDeltaRangeMeters()} is reset or there is a
* cycle slip (indicating 'loss of lock').
*/
- public short getAccumulatedDeltaRangeState() {
+ public int getAccumulatedDeltaRangeState() {
return mAccumulatedDeltaRangeState;
}
/**
* Sets the 'Accumulated Delta Range' state.
*/
- public void setAccumulatedDeltaRangeState(short value) {
+ public void setAccumulatedDeltaRangeState(int value) {
mAccumulatedDeltaRangeState = value;
}
@@ -545,24 +485,24 @@
/**
* Gets the accumulated delta range since the last channel reset, in meters.
- * The reported value includes {@link #getAccumulatedDeltaRangeUncertaintyInMeters()}.
+ * The reported value includes {@link #getAccumulatedDeltaRangeUncertaintyMeters()}.
*
* The availability of the value is represented by {@link #getAccumulatedDeltaRangeState()}.
*
* A positive value indicates that the SV is moving away from the receiver.
- * The sign of {@link #getAccumulatedDeltaRangeInMeters()} and its relation to the sign of
+ * The sign of {@link #getAccumulatedDeltaRangeMeters()} and its relation to the sign of
* {@link #getCarrierPhase()} is given by the equation:
* accumulated delta range = -k * carrier phase (where k is a constant)
*/
- public double getAccumulatedDeltaRangeInMeters() {
- return mAccumulatedDeltaRangeInMeters;
+ public double getAccumulatedDeltaRangeMeters() {
+ return mAccumulatedDeltaRangeMeters;
}
/**
* Sets the accumulated delta range in meters.
*/
- public void setAccumulatedDeltaRangeInMeters(double value) {
- mAccumulatedDeltaRangeInMeters = value;
+ public void setAccumulatedDeltaRangeMeters(double value) {
+ mAccumulatedDeltaRangeMeters = value;
}
/**
@@ -571,8 +511,8 @@
*
* The status of the value is represented by {@link #getAccumulatedDeltaRangeState()}.
*/
- public double getAccumulatedDeltaRangeUncertaintyInMeters() {
- return mAccumulatedDeltaRangeUncertaintyInMeters;
+ public double getAccumulatedDeltaRangeUncertaintyMeters() {
+ return mAccumulatedDeltaRangeUncertaintyMeters;
}
/**
@@ -580,149 +520,14 @@
*
* The status of the value is represented by {@link #getAccumulatedDeltaRangeState()}.
*/
- public void setAccumulatedDeltaRangeUncertaintyInMeters(double value) {
- mAccumulatedDeltaRangeUncertaintyInMeters = value;
+ public void setAccumulatedDeltaRangeUncertaintyMeters(double value) {
+ mAccumulatedDeltaRangeUncertaintyMeters = value;
}
/**
- * Returns true if {@link #getPseudorangeInMeters()} is available, false otherwise.
+ * Returns true if {@link #getCarrierFrequencyHz()} is available, false otherwise.
*/
- public boolean hasPseudorangeInMeters() {
- return isFlagSet(HAS_PSEUDORANGE);
- }
-
- /**
- * Gets the best derived pseudorange by the chipset, in meters.
- * The reported pseudorange includes {@link #getPseudorangeUncertaintyInMeters()}.
- *
- * The value is only available if {@link #hasPseudorangeInMeters()} is true.
- */
- public double getPseudorangeInMeters() {
- return mPseudorangeInMeters;
- }
-
- /**
- * Sets the Pseudo-range in meters.
- */
- public void setPseudorangeInMeters(double value) {
- setFlag(HAS_PSEUDORANGE);
- mPseudorangeInMeters = value;
- }
-
- /**
- * Resets the Pseudo-range in meters.
- */
- public void resetPseudorangeInMeters() {
- resetFlag(HAS_PSEUDORANGE);
- mPseudorangeInMeters = Double.NaN;
- }
-
- /**
- * Returns true if {@link #getPseudorangeUncertaintyInMeters()} is available, false otherwise.
- */
- public boolean hasPseudorangeUncertaintyInMeters() {
- return isFlagSet(HAS_PSEUDORANGE_UNCERTAINTY);
- }
-
- /**
- * Gets the pseudorange's uncertainty (1-Sigma) in meters.
- * The value contains the 'pseudorange' and 'clock' uncertainty in it.
- * The uncertainty is represented as an absolute (single sided) value.
- *
- * The value is only available if {@link #hasPseudorangeUncertaintyInMeters()} is true.
- */
- public double getPseudorangeUncertaintyInMeters() {
- return mPseudorangeUncertaintyInMeters;
- }
-
- /**
- * Sets the pseudo-range's uncertainty (1-Sigma) in meters.
- */
- public void setPseudorangeUncertaintyInMeters(double value) {
- setFlag(HAS_PSEUDORANGE_UNCERTAINTY);
- mPseudorangeUncertaintyInMeters = value;
- }
-
- /**
- * Resets the pseudo-range's uncertainty (1-Sigma) in meters.
- */
- public void resetPseudorangeUncertaintyInMeters() {
- resetFlag(HAS_PSEUDORANGE_UNCERTAINTY);
- mPseudorangeUncertaintyInMeters = Double.NaN;
- }
-
- /**
- * Returns true if {@link #getCodePhaseInChips()} is available, false otherwise.
- */
- public boolean hasCodePhaseInChips() {
- return isFlagSet(HAS_CODE_PHASE);
- }
-
- /**
- * Gets the fraction of the current C/A code cycle.
- * Range: [0, 1023]
- * The reference frequency is given by the value of {@link #getCarrierFrequencyInHz()}.
- * The reported code-phase includes {@link #getCodePhaseUncertaintyInChips()}.
- *
- * The value is only available if {@link #hasCodePhaseInChips()} is true.
- */
- public double getCodePhaseInChips() {
- return mCodePhaseInChips;
- }
-
- /**
- * Sets the Code-phase in chips.
- */
- public void setCodePhaseInChips(double value) {
- setFlag(HAS_CODE_PHASE);
- mCodePhaseInChips = value;
- }
-
- /**
- * Resets the Code-phase in chips.
- */
- public void resetCodePhaseInChips() {
- resetFlag(HAS_CODE_PHASE);
- mCodePhaseInChips = Double.NaN;
- }
-
- /**
- * Returns true if {@link #getCodePhaseUncertaintyInChips()} is available, false otherwise.
- */
- public boolean hasCodePhaseUncertaintyInChips() {
- return isFlagSet(HAS_CODE_PHASE_UNCERTAINTY);
- }
-
- /**
- * Gets the code-phase's uncertainty (1-Sigma) as a fraction of chips.
- * The uncertainty is represented as an absolute (single sided) value.
- *
- * The value is only available if {@link #hasCodePhaseUncertaintyInChips()} is true.
- */
- public double getCodePhaseUncertaintyInChips() {
- return mCodePhaseUncertaintyInChips;
- }
-
- /**
- * Sets the Code-phase's uncertainty (1-Sigma) in fractions of chips.
- */
- public void setCodePhaseUncertaintyInChips(double value) {
- setFlag(HAS_CODE_PHASE_UNCERTAINTY);
- mCodePhaseUncertaintyInChips = value;
- }
-
- /**
- * Resets the Code-phase's uncertainty (1-Sigma) in fractions of chips.
- */
- public void resetCodePhaseUncertaintyInChips() {
- resetFlag(HAS_CODE_PHASE_UNCERTAINTY);
- mCodePhaseUncertaintyInChips = Double.NaN;
- }
-
- /**
- * Returns true if {@link #getCarrierFrequencyInHz()} is available, false otherwise.
- */
- public boolean hasCarrierFrequencyInHz() {
+ public boolean hasCarrierFrequencyHz() {
return isFlagSet(HAS_CARRIER_FREQUENCY);
}
@@ -730,26 +535,26 @@
* Gets the carrier frequency at which codes and messages are modulated, it can be L1 or L2.
* If the field is not set, the carrier frequency corresponds to L1.
*
- * The value is only available if {@link #hasCarrierFrequencyInHz()} is true.
+ * The value is only available if {@link #hasCarrierFrequencyHz()} is true.
*/
- public float getCarrierFrequencyInHz() {
- return mCarrierFrequencyInHz;
+ public float getCarrierFrequencyHz() {
+ return mCarrierFrequencyHz;
}
/**
* Sets the Carrier frequency (L1 or L2) in Hz.
*/
- public void setCarrierFrequencyInHz(float carrierFrequencyInHz) {
+ public void setCarrierFrequencyHz(float carrierFrequencyHz) {
setFlag(HAS_CARRIER_FREQUENCY);
- mCarrierFrequencyInHz = carrierFrequencyInHz;
+ mCarrierFrequencyHz = carrierFrequencyHz;
}
/**
* Resets the Carrier frequency (L1 or L2) in Hz.
*/
- public void resetCarrierFrequencyInHz() {
+ public void resetCarrierFrequencyHz() {
resetFlag(HAS_CARRIER_FREQUENCY);
- mCarrierFrequencyInHz = Float.NaN;
+ mCarrierFrequencyHz = Float.NaN;
}
/**
@@ -761,7 +566,7 @@
/**
* The number of full carrier cycles between the satellite and the receiver.
- * The reference frequency is given by the value of {@link #getCarrierFrequencyInHz()}.
+ * The reference frequency is given by the value of {@link #getCarrierFrequencyHz()}.
*
* The value is only available if {@link #hasCarrierCycles()} is true.
*/
@@ -797,7 +602,7 @@
* Range: [0.0, 1.0].
* This is usually the fractional part of the complete carrier phase measurement.
*
- * The reference frequency is given by the value of {@link #getCarrierFrequencyInHz()}.
+ * The reference frequency is given by the value of {@link #getCarrierFrequencyHz()}.
* The reported carrier-phase includes {@link #getCarrierPhaseUncertainty()}.
*
* The value is only available if {@link #hasCarrierPhase()} is true.
@@ -856,183 +661,17 @@
}
/**
- * Gets a value indicating the 'loss of lock' state of the event.
- */
- @LossOfLockStatus
- public byte getLossOfLock() {
- return mLossOfLock;
- }
-
- /**
- * Sets the 'loss of lock' status.
- */
- public void setLossOfLock(@LossOfLockStatus byte value) {
- mLossOfLock = value;
- }
-
- /**
- * Gets a string representation of the 'loss of lock'.
- * For internal and logging use only.
- */
- private String getLossOfLockString() {
- switch (mLossOfLock) {
- case LOSS_OF_LOCK_UNKNOWN:
- return "Unknown";
- case LOSS_OF_LOCK_OK:
- return "Ok";
- case LOSS_OF_LOCK_CYCLE_SLIP:
- return "CycleSlip";
- default:
- return "<Invalid:" + mLossOfLock + ">";
- }
- }
-
- /**
- * Returns true if {@link #getBitNumber()} is available, false otherwise.
- */
- public boolean hasBitNumber() {
- return isFlagSet(HAS_BIT_NUMBER);
- }
-
- /**
- * Gets the number of GPS bits transmitted since Sat-Sun midnight (GPS week).
- *
- * The value is only available if {@link #hasBitNumber()} is true.
- */
- public int getBitNumber() {
- return mBitNumber;
- }
-
- /**
- * Sets the bit number within the broadcast frame.
- */
- public void setBitNumber(int bitNumber) {
- setFlag(HAS_BIT_NUMBER);
- mBitNumber = bitNumber;
- }
-
- /**
- * Resets the bit number within the broadcast frame.
- */
- public void resetBitNumber() {
- resetFlag(HAS_BIT_NUMBER);
- mBitNumber = Integer.MIN_VALUE;
- }
-
- /**
- * Returns true if {@link #getTimeFromLastBitInMs()} is available, false otherwise.
- */
- public boolean hasTimeFromLastBitInMs() {
- return isFlagSet(HAS_TIME_FROM_LAST_BIT);
- }
-
- /**
- * Gets the elapsed time since the last received bit in milliseconds.
- * Range: [0, 20].
- *
- * The value is only available if {@link #hasTimeFromLastBitInMs()} is true.
- */
- public short getTimeFromLastBitInMs() {
- return mTimeFromLastBitInMs;
- }
-
- /**
- * Sets the elapsed time since the last received bit in milliseconds.
- */
- public void setTimeFromLastBitInMs(short value) {
- setFlag(HAS_TIME_FROM_LAST_BIT);
- mTimeFromLastBitInMs = value;
- }
-
- /**
- * Resets the elapsed time since the last received bit in milliseconds.
- */
- public void resetTimeFromLastBitInMs() {
- resetFlag(HAS_TIME_FROM_LAST_BIT);
- mTimeFromLastBitInMs = Short.MIN_VALUE;
- }
-
- /**
- * Returns true if {@link #getDopplerShiftInHz()} is available, false otherwise.
- */
- public boolean hasDopplerShiftInHz() {
- return isFlagSet(HAS_DOPPLER_SHIFT);
- }
-
- /**
- * Gets the Doppler Shift in Hz.
- * A positive value indicates that the SV is moving toward the receiver.
- *
- * The reference frequency is given by the value of {@link #getCarrierFrequencyInHz()}.
- * The reported doppler shift includes {@link #getDopplerShiftUncertaintyInHz()}.
- *
- * The value is only available if {@link #hasDopplerShiftInHz()} is true.
- */
- public double getDopplerShiftInHz() {
- return mDopplerShiftInHz;
- }
-
- /**
- * Sets the Doppler shift in Hz.
- */
- public void setDopplerShiftInHz(double value) {
- setFlag(HAS_DOPPLER_SHIFT);
- mDopplerShiftInHz = value;
- }
-
- /**
- * Resets the Doppler shift in Hz.
- */
- public void resetDopplerShiftInHz() {
- resetFlag(HAS_DOPPLER_SHIFT);
- mDopplerShiftInHz = Double.NaN;
- }
-
- /**
- * Returns true if {@link #getDopplerShiftUncertaintyInHz()} is available, false otherwise.
- */
- public boolean hasDopplerShiftUncertaintyInHz() {
- return isFlagSet(HAS_DOPPLER_SHIFT_UNCERTAINTY);
- }
-
- /**
- * Gets the Doppler's Shift uncertainty (1-Sigma) in Hz.
- * The uncertainty is represented as an absolute (single sided) value.
- *
- * The value is only available if {@link #hasDopplerShiftUncertaintyInHz()} is true.
- */
- public double getDopplerShiftUncertaintyInHz() {
- return mDopplerShiftUncertaintyInHz;
- }
-
- /**
- * Sets the Doppler's shift uncertainty (1-Sigma) in Hz.
- */
- public void setDopplerShiftUncertaintyInHz(double value) {
- setFlag(HAS_DOPPLER_SHIFT_UNCERTAINTY);
- mDopplerShiftUncertaintyInHz = value;
- }
-
- /**
- * Resets the Doppler's shift uncertainty (1-Sigma) in Hz.
- */
- public void resetDopplerShiftUncertaintyInHz() {
- resetFlag(HAS_DOPPLER_SHIFT_UNCERTAINTY);
- mDopplerShiftUncertaintyInHz = Double.NaN;
- }
-
- /**
* Gets a value indicating the 'multipath' state of the event.
*/
@MultipathIndicator
- public byte getMultipathIndicator() {
+ public int getMultipathIndicator() {
return mMultipathIndicator;
}
/**
* Sets the 'multi-path' indicator.
*/
- public void setMultipathIndicator(@MultipathIndicator byte value) {
+ public void setMultipathIndicator(@MultipathIndicator int value) {
mMultipathIndicator = value;
}
@@ -1085,200 +724,30 @@
mSnrInDb = Double.NaN;
}
- /**
- * Returns true if {@link #getElevationInDeg()} is available, false otherwise.
- */
- public boolean hasElevationInDeg() {
- return isFlagSet(HAS_ELEVATION);
- }
-
- /**
- * Gets the Elevation in degrees.
- * Range: [-90, 90]
- * The reported elevation includes {@link #getElevationUncertaintyInDeg()}.
- *
- * The value is only available if {@link #hasElevationInDeg()} is true.
- */
- public double getElevationInDeg() {
- return mElevationInDeg;
- }
-
- /**
- * Sets the Elevation in degrees.
- */
- public void setElevationInDeg(double elevationInDeg) {
- setFlag(HAS_ELEVATION);
- mElevationInDeg = elevationInDeg;
- }
-
- /**
- * Resets the Elevation in degrees.
- */
- public void resetElevationInDeg() {
- resetFlag(HAS_ELEVATION);
- mElevationInDeg = Double.NaN;
- }
-
- /**
- * Returns true if {@link #getElevationUncertaintyInDeg()} is available, false otherwise.
- */
- public boolean hasElevationUncertaintyInDeg() {
- return isFlagSet(HAS_ELEVATION_UNCERTAINTY);
- }
-
- /**
- * Gets the elevation's uncertainty (1-Sigma) in degrees.
- * Range: [0, 90]
- *
- * The uncertainty is represented as an absolute (single sided) value.
- *
- * The value is only available if {@link #hasElevationUncertaintyInDeg()} is true.
- */
- public double getElevationUncertaintyInDeg() {
- return mElevationUncertaintyInDeg;
- }
-
- /**
- * Sets the elevation's uncertainty (1-Sigma) in degrees.
- */
- public void setElevationUncertaintyInDeg(double value) {
- setFlag(HAS_ELEVATION_UNCERTAINTY);
- mElevationUncertaintyInDeg = value;
- }
-
- /**
- * Resets the elevation's uncertainty (1-Sigma) in degrees.
- */
- public void resetElevationUncertaintyInDeg() {
- resetFlag(HAS_ELEVATION_UNCERTAINTY);
- mElevationUncertaintyInDeg = Double.NaN;
- }
-
- /**
- * Returns true if {@link #getAzimuthInDeg()} is available, false otherwise.
- */
- public boolean hasAzimuthInDeg() {
- return isFlagSet(HAS_AZIMUTH);
- }
-
- /**
- * Gets the azimuth in degrees.
- * Range: [0, 360).
- *
- * The reported azimuth includes {@link #getAzimuthUncertaintyInDeg()}.
- *
- * The value is only available if {@link #hasAzimuthInDeg()} is true.
- */
- public double getAzimuthInDeg() {
- return mAzimuthInDeg;
- }
-
- /**
- * Sets the Azimuth in degrees.
- */
- public void setAzimuthInDeg(double value) {
- setFlag(HAS_AZIMUTH);
- mAzimuthInDeg = value;
- }
-
- /**
- * Resets the Azimuth in degrees.
- */
- public void resetAzimuthInDeg() {
- resetFlag(HAS_AZIMUTH);
- mAzimuthInDeg = Double.NaN;
- }
-
- /**
- * Returns true if {@link #getAzimuthUncertaintyInDeg()} is available, false otherwise.
- */
- public boolean hasAzimuthUncertaintyInDeg() {
- return isFlagSet(HAS_AZIMUTH_UNCERTAINTY);
- }
-
- /**
- * Gets the azimuth's uncertainty (1-Sigma) in degrees.
- * Range: [0, 180].
- *
- * The uncertainty is represented as an absolute (single sided) value.
- *
- * The value is only available if {@link #hasAzimuthUncertaintyInDeg()} is true.
- */
- public double getAzimuthUncertaintyInDeg() {
- return mAzimuthUncertaintyInDeg;
- }
-
- /**
- * Sets the Azimuth's uncertainty (1-Sigma) in degrees.
- */
- public void setAzimuthUncertaintyInDeg(double value) {
- setFlag(HAS_AZIMUTH_UNCERTAINTY);
- mAzimuthUncertaintyInDeg = value;
- }
-
- /**
- * Resets the Azimuth's uncertainty (1-Sigma) in degrees.
- */
- public void resetAzimuthUncertaintyInDeg() {
- resetFlag(HAS_AZIMUTH_UNCERTAINTY);
- mAzimuthUncertaintyInDeg = Double.NaN;
- }
-
- /**
- * Gets a flag indicating whether the GNSS represented by the measurement was used for computing
- * the most recent fix.
- *
- * @return A non-null value if the data is available, null otherwise.
- */
- public boolean isUsedInFix() {
- return mUsedInFix;
- }
-
- /**
- * Sets the Used-in-Fix flag.
- */
- public void setUsedInFix(boolean value) {
- mUsedInFix = value;
- }
-
public static final Creator<GnssMeasurement> CREATOR = new Creator<GnssMeasurement>() {
@Override
public GnssMeasurement createFromParcel(Parcel parcel) {
GnssMeasurement gnssMeasurement = new GnssMeasurement();
gnssMeasurement.mFlags = parcel.readInt();
- gnssMeasurement.mSvid = (short) parcel.readInt();
- gnssMeasurement.mConstellationType = parcel.readByte();
- gnssMeasurement.mTimeOffsetInNs = parcel.readDouble();
- gnssMeasurement.mState = (short) parcel.readInt();
- gnssMeasurement.mReceivedSvTimeInNs = parcel.readLong();
- gnssMeasurement.mReceivedSvTimeUncertaintyInNs = parcel.readLong();
- gnssMeasurement.mCn0InDbHz = parcel.readDouble();
- gnssMeasurement.mPseudorangeRateInMetersPerSec = parcel.readDouble();
- gnssMeasurement.mPseudorangeRateUncertaintyInMetersPerSec = parcel.readDouble();
- gnssMeasurement.mAccumulatedDeltaRangeState = (short) parcel.readInt();
- gnssMeasurement.mAccumulatedDeltaRangeInMeters = parcel.readDouble();
- gnssMeasurement.mAccumulatedDeltaRangeUncertaintyInMeters = parcel.readDouble();
- gnssMeasurement.mPseudorangeInMeters = parcel.readDouble();
- gnssMeasurement.mPseudorangeUncertaintyInMeters = parcel.readDouble();
- gnssMeasurement.mCodePhaseInChips = parcel.readDouble();
- gnssMeasurement.mCodePhaseUncertaintyInChips = parcel.readDouble();
- gnssMeasurement.mCarrierFrequencyInHz = parcel.readFloat();
+ gnssMeasurement.mSvid = parcel.readInt();
+ gnssMeasurement.mConstellationType = parcel.readInt();
+ gnssMeasurement.mTimeOffsetNanos = parcel.readDouble();
+ gnssMeasurement.mState = parcel.readInt();
+ gnssMeasurement.mReceivedSvTimeNanos = parcel.readLong();
+ gnssMeasurement.mReceivedSvTimeUncertaintyNanos = parcel.readLong();
+ gnssMeasurement.mCn0DbHz = parcel.readDouble();
+ gnssMeasurement.mPseudorangeRateMetersPerSecond = parcel.readDouble();
+ gnssMeasurement.mPseudorangeRateUncertaintyMetersPerSecond = parcel.readDouble();
+ gnssMeasurement.mAccumulatedDeltaRangeState = parcel.readInt();
+ gnssMeasurement.mAccumulatedDeltaRangeMeters = parcel.readDouble();
+ gnssMeasurement.mAccumulatedDeltaRangeUncertaintyMeters = parcel.readDouble();
+ gnssMeasurement.mCarrierFrequencyHz = parcel.readFloat();
gnssMeasurement.mCarrierCycles = parcel.readLong();
gnssMeasurement.mCarrierPhase = parcel.readDouble();
gnssMeasurement.mCarrierPhaseUncertainty = parcel.readDouble();
- gnssMeasurement.mLossOfLock = parcel.readByte();
- gnssMeasurement.mBitNumber = parcel.readInt();
- gnssMeasurement.mTimeFromLastBitInMs = (short) parcel.readInt();
- gnssMeasurement.mDopplerShiftInHz = parcel.readDouble();
- gnssMeasurement.mDopplerShiftUncertaintyInHz = parcel.readDouble();
- gnssMeasurement.mMultipathIndicator = parcel.readByte();
+ gnssMeasurement.mMultipathIndicator = parcel.readInt();
gnssMeasurement.mSnrInDb = parcel.readDouble();
- gnssMeasurement.mElevationInDeg = parcel.readDouble();
- gnssMeasurement.mElevationUncertaintyInDeg = parcel.readDouble();
- gnssMeasurement.mAzimuthInDeg = parcel.readDouble();
- gnssMeasurement.mAzimuthUncertaintyInDeg = parcel.readDouble();
- gnssMeasurement.mUsedInFix = parcel.readInt() != 0;
return gnssMeasurement;
}
@@ -1293,37 +762,23 @@
public void writeToParcel(Parcel parcel, int flags) {
parcel.writeInt(mFlags);
parcel.writeInt(mSvid);
- parcel.writeByte(mConstellationType);
- parcel.writeDouble(mTimeOffsetInNs);
+ parcel.writeInt(mConstellationType);
+ parcel.writeDouble(mTimeOffsetNanos);
parcel.writeInt(mState);
- parcel.writeLong(mReceivedSvTimeInNs);
- parcel.writeLong(mReceivedSvTimeUncertaintyInNs);
- parcel.writeDouble(mCn0InDbHz);
- parcel.writeDouble(mPseudorangeRateInMetersPerSec);
- parcel.writeDouble(mPseudorangeRateUncertaintyInMetersPerSec);
+ parcel.writeLong(mReceivedSvTimeNanos);
+ parcel.writeLong(mReceivedSvTimeUncertaintyNanos);
+ parcel.writeDouble(mCn0DbHz);
+ parcel.writeDouble(mPseudorangeRateMetersPerSecond);
+ parcel.writeDouble(mPseudorangeRateUncertaintyMetersPerSecond);
parcel.writeInt(mAccumulatedDeltaRangeState);
- parcel.writeDouble(mAccumulatedDeltaRangeInMeters);
- parcel.writeDouble(mAccumulatedDeltaRangeUncertaintyInMeters);
- parcel.writeDouble(mPseudorangeInMeters);
- parcel.writeDouble(mPseudorangeUncertaintyInMeters);
- parcel.writeDouble(mCodePhaseInChips);
- parcel.writeDouble(mCodePhaseUncertaintyInChips);
- parcel.writeFloat(mCarrierFrequencyInHz);
+ parcel.writeDouble(mAccumulatedDeltaRangeMeters);
+ parcel.writeDouble(mAccumulatedDeltaRangeUncertaintyMeters);
+ parcel.writeFloat(mCarrierFrequencyHz);
parcel.writeLong(mCarrierCycles);
parcel.writeDouble(mCarrierPhase);
parcel.writeDouble(mCarrierPhaseUncertainty);
- parcel.writeByte(mLossOfLock);
- parcel.writeInt(mBitNumber);
- parcel.writeInt(mTimeFromLastBitInMs);
- parcel.writeDouble(mDopplerShiftInHz);
- parcel.writeDouble(mDopplerShiftUncertaintyInHz);
- parcel.writeByte(mMultipathIndicator);
+ parcel.writeInt(mMultipathIndicator);
parcel.writeDouble(mSnrInDb);
- parcel.writeDouble(mElevationInDeg);
- parcel.writeDouble(mElevationUncertaintyInDeg);
- parcel.writeDouble(mAzimuthInDeg);
- parcel.writeDouble(mAzimuthUncertaintyInDeg);
- parcel.writeInt(mUsedInFix ? 1 : 0);
}
@Override
@@ -1339,25 +794,25 @@
builder.append(String.format(format, "Svid", mSvid));
builder.append(String.format(format, "ConstellationType", mConstellationType));
- builder.append(String.format(format, "TimeOffsetInNs", mTimeOffsetInNs));
+ builder.append(String.format(format, "TimeOffsetNanos", mTimeOffsetNanos));
builder.append(String.format(format, "State", getStateString()));
builder.append(String.format(
formatWithUncertainty,
- "ReceivedSvTimeInNs",
- mReceivedSvTimeInNs,
- "ReceivedSvTimeUncertaintyInNs",
- mReceivedSvTimeUncertaintyInNs));
+ "ReceivedSvTimeNanos",
+ mReceivedSvTimeNanos,
+ "ReceivedSvTimeUncertaintyNanos",
+ mReceivedSvTimeUncertaintyNanos));
- builder.append(String.format(format, "Cn0InDbHz", mCn0InDbHz));
+ builder.append(String.format(format, "Cn0DbHz", mCn0DbHz));
builder.append(String.format(
formatWithUncertainty,
- "PseudorangeRateInMetersPerSec",
- mPseudorangeRateInMetersPerSec,
- "PseudorangeRateUncertaintyInMetersPerSec",
- mPseudorangeRateUncertaintyInMetersPerSec));
+ "PseudorangeRateMetersPerSecond",
+ mPseudorangeRateMetersPerSecond,
+ "PseudorangeRateUncertaintyMetersPerSecond",
+ mPseudorangeRateUncertaintyMetersPerSecond));
builder.append(String.format(
format,
"PseudorangeRateIsCorrected",
@@ -1370,29 +825,15 @@
builder.append(String.format(
formatWithUncertainty,
- "AccumulatedDeltaRangeInMeters",
- mAccumulatedDeltaRangeInMeters,
- "AccumulatedDeltaRangeUncertaintyInMeters",
- mAccumulatedDeltaRangeUncertaintyInMeters));
-
- builder.append(String.format(
- formatWithUncertainty,
- "PseudorangeInMeters",
- hasPseudorangeInMeters() ? mPseudorangeInMeters : null,
- "PseudorangeUncertaintyInMeters",
- hasPseudorangeUncertaintyInMeters() ? mPseudorangeUncertaintyInMeters : null));
-
- builder.append(String.format(
- formatWithUncertainty,
- "CodePhaseInChips",
- hasCodePhaseInChips() ? mCodePhaseInChips : null,
- "CodePhaseUncertaintyInChips",
- hasCodePhaseUncertaintyInChips() ? mCodePhaseUncertaintyInChips : null));
+ "AccumulatedDeltaRangeMeters",
+ mAccumulatedDeltaRangeMeters,
+ "AccumulatedDeltaRangeUncertaintyMeters",
+ mAccumulatedDeltaRangeUncertaintyMeters));
builder.append(String.format(
format,
- "CarrierFrequencyInHz",
- hasCarrierFrequencyInHz() ? mCarrierFrequencyInHz : null));
+ "CarrierFrequencyHz",
+ hasCarrierFrequencyHz() ? mCarrierFrequencyHz : null));
builder.append(String.format(
format,
@@ -1406,25 +847,6 @@
"CarrierPhaseUncertainty",
hasCarrierPhaseUncertainty() ? mCarrierPhaseUncertainty : null));
- builder.append(String.format(format, "LossOfLock", getLossOfLockString()));
-
- builder.append(String.format(
- format,
- "BitNumber",
- hasBitNumber() ? mBitNumber : null));
-
- builder.append(String.format(
- format,
- "TimeFromLastBitInMs",
- hasTimeFromLastBitInMs() ? mTimeFromLastBitInMs : null));
-
- builder.append(String.format(
- formatWithUncertainty,
- "DopplerShiftInHz",
- hasDopplerShiftInHz() ? mDopplerShiftInHz : null,
- "DopplerShiftUncertaintyInHz",
- hasDopplerShiftUncertaintyInHz() ? mDopplerShiftUncertaintyInHz : null));
-
builder.append(String.format(format, "MultipathIndicator", getMultipathIndicatorString()));
builder.append(String.format(
@@ -1432,58 +854,28 @@
"SnrInDb",
hasSnrInDb() ? mSnrInDb : null));
- builder.append(String.format(
- formatWithUncertainty,
- "ElevationInDeg",
- hasElevationInDeg() ? mElevationInDeg : null,
- "ElevationUncertaintyInDeg",
- hasElevationUncertaintyInDeg() ? mElevationUncertaintyInDeg : null));
-
- builder.append(String.format(
- formatWithUncertainty,
- "AzimuthInDeg",
- hasAzimuthInDeg() ? mAzimuthInDeg : null,
- "AzimuthUncertaintyInDeg",
- hasAzimuthUncertaintyInDeg() ? mAzimuthUncertaintyInDeg : null));
-
- builder.append(String.format(format, "UsedInFix", mUsedInFix));
-
return builder.toString();
}
private void initialize() {
mFlags = HAS_NO_FLAGS;
- setSvid((short) 0);
- setTimeOffsetInNs(Long.MIN_VALUE);
+ setSvid(0);
+ setTimeOffsetNanos(Long.MIN_VALUE);
setState(STATE_UNKNOWN);
- setReceivedSvTimeInNs(Long.MIN_VALUE);
- setReceivedSvTimeUncertaintyInNs(Long.MAX_VALUE);
- setCn0InDbHz(Double.MIN_VALUE);
- setPseudorangeRateInMetersPerSec(Double.MIN_VALUE);
- setPseudorangeRateUncertaintyInMetersPerSec(Double.MIN_VALUE);
+ setReceivedSvTimeNanos(Long.MIN_VALUE);
+ setReceivedSvTimeUncertaintyNanos(Long.MAX_VALUE);
+ setCn0DbHz(Double.MIN_VALUE);
+ setPseudorangeRateMetersPerSecond(Double.MIN_VALUE);
+ setPseudorangeRateUncertaintyMetersPerSecond(Double.MIN_VALUE);
setAccumulatedDeltaRangeState(ADR_STATE_UNKNOWN);
- setAccumulatedDeltaRangeInMeters(Double.MIN_VALUE);
- setAccumulatedDeltaRangeUncertaintyInMeters(Double.MIN_VALUE);
- resetPseudorangeInMeters();
- resetPseudorangeUncertaintyInMeters();
- resetCodePhaseInChips();
- resetCodePhaseUncertaintyInChips();
- resetCarrierFrequencyInHz();
+ setAccumulatedDeltaRangeMeters(Double.MIN_VALUE);
+ setAccumulatedDeltaRangeUncertaintyMeters(Double.MIN_VALUE);
+ resetCarrierFrequencyHz();
resetCarrierCycles();
resetCarrierPhase();
resetCarrierPhaseUncertainty();
- setLossOfLock(LOSS_OF_LOCK_UNKNOWN);
- resetBitNumber();
- resetTimeFromLastBitInMs();
- resetDopplerShiftInHz();
- resetDopplerShiftUncertaintyInHz();
setMultipathIndicator(MULTIPATH_INDICATOR_UNKNOWN);
resetSnrInDb();
- resetElevationInDeg();
- resetElevationUncertaintyInDeg();
- resetAzimuthInDeg();
- resetAzimuthUncertaintyInDeg();
- setUsedInFix(false);
}
private void setFlag(int flag) {
diff --git a/location/java/android/location/GnssMeasurementsEvent.java b/location/java/android/location/GnssMeasurementsEvent.java
index b744a03..86841ff 100644
--- a/location/java/android/location/GnssMeasurementsEvent.java
+++ b/location/java/android/location/GnssMeasurementsEvent.java
@@ -33,46 +33,46 @@
* Events are delivered to registered instances of {@link Callback}.
*/
public final class GnssMeasurementsEvent implements Parcelable {
- /** The status of GPS measurements event. */
+ /** The status of GNSS measurements event. */
@Retention(RetentionPolicy.SOURCE)
- @IntDef({STATUS_NOT_SUPPORTED, STATUS_READY, STATUS_GPS_LOCATION_DISABLED})
+ @IntDef({STATUS_NOT_SUPPORTED, STATUS_READY, STATUS_GNSS_LOCATION_DISABLED})
public @interface GnssMeasurementsStatus {}
/**
- * The system does not support tracking of GPS Measurements. This status will not change in the
+ * The system does not support tracking of GNSS Measurements. This status will not change in the
* future.
*/
public static final int STATUS_NOT_SUPPORTED = 0;
/**
- * GPS Measurements are successfully being tracked, it will receive updates once they are
+ * GNSS Measurements are successfully being tracked, it will receive updates once they are
* available.
*/
public static final int STATUS_READY = 1;
/**
- * GPS provider or Location is disabled, updates will not be received until they are enabled.
+ * GNSS provider or Location is disabled, updates will not be received until they are enabled.
*/
- public static final int STATUS_GPS_LOCATION_DISABLED = 2;
+ public static final int STATUS_GNSS_LOCATION_DISABLED = 2;
private final GnssClock mClock;
private final Collection<GnssMeasurement> mReadOnlyMeasurements;
/**
- * Used for receiving GPS satellite measurements from the GPS engine.
+ * Used for receiving GNSS satellite measurements from the GNSS engine.
* Each measurement contains raw and computed data identifying a satellite.
* You can implement this interface and call
- * {@link LocationManager#registerGnssMeasurementCallback}.
+ * {@link LocationManager#registerGnssMeasurementsCallback}.
*/
public static abstract class Callback {
/**
- * Returns the latest collected GPS Measurements.
+ * Reports the latest collected GNSS Measurements.
*/
public void onGnssMeasurementsReceived(GnssMeasurementsEvent eventArgs) {}
/**
- * Returns the latest status of the GPS Measurements sub-system.
+ * Reports the latest status of the GNSS Measurements sub-system.
*/
public void onStatusChanged(@GnssMeasurementsStatus int status) {}
}
diff --git a/location/java/android/location/GnssNavigationMessage.java b/location/java/android/location/GnssNavigationMessage.java
index faefd0bb..c0608e0 100644
--- a/location/java/android/location/GnssNavigationMessage.java
+++ b/location/java/android/location/GnssNavigationMessage.java
@@ -34,58 +34,57 @@
/** The type of the GPS Clock. */
@Retention(RetentionPolicy.SOURCE)
- @IntDef({MESSAGE_TYPE_UNKNOWN, MESSAGE_TYPE_GPS_L1CA, MESSAGE_TYPE_GPS_L2CNAV,
- MESSAGE_TYPE_GPS_L5CNAV, MESSAGE_TYPE_GPS_CNAV2, MESSAGE_TYPE_GLO_L1CA, MESSAGE_TYPE_BDS_D1,
- MESSAGE_TYPE_BDS_D2, MESSAGE_TYPE_GAL_I, MESSAGE_TYPE_GAL_F})
+ @IntDef({TYPE_UNKNOWN, TYPE_GPS_L1CA, TYPE_GPS_L2CNAV, TYPE_GPS_L5CNAV, TYPE_GPS_CNAV2,
+ TYPE_GLO_L1CA, TYPE_BDS_D1, TYPE_BDS_D2, TYPE_GAL_I, TYPE_GAL_F})
public @interface GnssNavigationMessageType {}
// The following enumerations must be in sync with the values declared in gps.h
/** Message type unknown */
- public static final short MESSAGE_TYPE_UNKNOWN = 0;
+ public static final int TYPE_UNKNOWN = 0;
/** GPS L1 C/A message contained in the structure. */
- public static final short MESSAGE_TYPE_GPS_L1CA = 0x0101;
+ public static final int TYPE_GPS_L1CA = 0x0101;
/** GPS L2-CNAV message contained in the structure. */
- public static final short MESSAGE_TYPE_GPS_L2CNAV = 0x0102;
+ public static final int TYPE_GPS_L2CNAV = 0x0102;
/** GPS L5-CNAV message contained in the structure. */
- public static final short MESSAGE_TYPE_GPS_L5CNAV = 0x0103;
+ public static final int TYPE_GPS_L5CNAV = 0x0103;
/** GPS CNAV-2 message contained in the structure. */
- public static final short MESSAGE_TYPE_GPS_CNAV2 = 0x0104;
+ public static final int TYPE_GPS_CNAV2 = 0x0104;
/** Glonass L1 CA message contained in the structure. */
- public static final short MESSAGE_TYPE_GLO_L1CA = 0x0301;
+ public static final int TYPE_GLO_L1CA = 0x0301;
/** Beidou D1 message contained in the structure. */
- public static final short MESSAGE_TYPE_BDS_D1 = 0x0501;
+ public static final int TYPE_BDS_D1 = 0x0501;
/** Beidou D2 message contained in the structure. */
- public static final short MESSAGE_TYPE_BDS_D2 = 0x0502;
+ public static final int TYPE_BDS_D2 = 0x0502;
/** Galileo I/NAV message contained in the structure. */
- public static final short MESSAGE_TYPE_GAL_I = 0x0601;
+ public static final int TYPE_GAL_I = 0x0601;
/** Galileo F/NAV message contained in the structure. */
- public static final short MESSAGE_TYPE_GAL_F = 0x0602;
+ public static final int TYPE_GAL_F = 0x0602;
/**
* The Navigation Message Status is 'unknown'.
*/
- public static final short STATUS_UNKNOWN = 0;
+ public static final int STATUS_UNKNOWN = 0;
/**
* The Navigation Message was received without any parity error in its navigation words.
*/
- public static final short STATUS_PARITY_PASSED = (1<<0);
+ public static final int STATUS_PARITY_PASSED = (1<<0);
/**
* The Navigation Message was received with words that failed parity check, but the receiver was
* able to correct those words.
*/
- public static final short STATUS_PARITY_REBUILT = (1<<1);
+ public static final int STATUS_PARITY_REBUILT = (1<<1);
// End enumerations in sync with gps.h
- private short mType;
- private short mSvid;
- private short mMessageId;
- private short mSubmessageId;
+ private int mType;
+ private int mSvid;
+ private int mMessageId;
+ private int mSubmessageId;
private byte[] mData;
- private short mStatus;
+ private int mStatus;
GnssNavigationMessage() {
initialize();
@@ -114,14 +113,14 @@
* Gets the type of the navigation message contained in the object.
*/
@GnssNavigationMessageType
- public short getType() {
+ public int getType() {
return mType;
}
/**
* Sets the type of the navigation message.
*/
- public void setType(@GnssNavigationMessageType short value) {
+ public void setType(@GnssNavigationMessageType int value) {
mType = value;
}
@@ -131,25 +130,25 @@
*/
private String getTypeString() {
switch (mType) {
- case MESSAGE_TYPE_UNKNOWN:
+ case TYPE_UNKNOWN:
return "Unknown";
- case MESSAGE_TYPE_GPS_L1CA:
+ case TYPE_GPS_L1CA:
return "GPS L1 C/A";
- case MESSAGE_TYPE_GPS_L2CNAV:
+ case TYPE_GPS_L2CNAV:
return "GPS L2-CNAV";
- case MESSAGE_TYPE_GPS_L5CNAV:
+ case TYPE_GPS_L5CNAV:
return "GPS L5-CNAV";
- case MESSAGE_TYPE_GPS_CNAV2:
+ case TYPE_GPS_CNAV2:
return "GPS CNAV2";
- case MESSAGE_TYPE_GLO_L1CA:
+ case TYPE_GLO_L1CA:
return "Glonass L1 C/A";
- case MESSAGE_TYPE_BDS_D1:
+ case TYPE_BDS_D1:
return "Beidou D1";
- case MESSAGE_TYPE_BDS_D2:
+ case TYPE_BDS_D2:
return "Beidou D2";
- case MESSAGE_TYPE_GAL_I:
+ case TYPE_GAL_I:
return "Galileo I";
- case MESSAGE_TYPE_GAL_F:
+ case TYPE_GAL_F:
return "Galileo F";
default:
return "<Invalid:" + mType + ">";
@@ -160,14 +159,14 @@
* Gets the Pseudo-random number.
* Range: [1, 32].
*/
- public short getSvid() {
+ public int getSvid() {
return mSvid;
}
/**
* Sets the Pseud-random number.
*/
- public void setSvid(short value) {
+ public void setSvid(int value) {
mSvid = value;
}
@@ -177,14 +176,14 @@
* subframe 4 and 5, this value corresponds to the 'frame id' of the navigation message.
* Subframe 1, 2, 3 does not contain a 'frame id' and this might be reported as -1.
*/
- public short getMessageId() {
+ public int getMessageId() {
return mMessageId;
}
/**
* Sets the Message Identifier.
*/
- public void setMessageId(short value) {
+ public void setMessageId(int value) {
mMessageId = value;
}
@@ -194,14 +193,14 @@
* (or frame) that is being transmitted. i.e. for L1 C/A the sub-message identifier corresponds
* to the sub-frame Id of the navigation message.
*/
- public short getSubmessageId() {
+ public int getSubmessageId() {
return mSubmessageId;
}
/**
* Sets the Sub-message identifier.
*/
- public void setSubmessageId(short value) {
+ public void setSubmessageId(int value) {
mSubmessageId = value;
}
@@ -228,14 +227,14 @@
/**
* Gets the Status of the navigation message contained in the object.
*/
- public short getStatus() {
+ public int getStatus() {
return mStatus;
}
/**
* Sets the status of the navigation message.
*/
- public void setStatus(short value) {
+ public void setStatus(int value) {
mStatus = value;
}
@@ -262,10 +261,10 @@
public GnssNavigationMessage createFromParcel(Parcel parcel) {
GnssNavigationMessage navigationMessage = new GnssNavigationMessage();
- navigationMessage.setType((short) parcel.readInt());
- navigationMessage.setSvid((short) parcel.readInt());
- navigationMessage.setMessageId((short) parcel.readInt());
- navigationMessage.setSubmessageId((short) parcel.readInt());
+ navigationMessage.setType(parcel.readInt());
+ navigationMessage.setSvid(parcel.readInt());
+ navigationMessage.setMessageId(parcel.readInt());
+ navigationMessage.setSubmessageId(parcel.readInt());
int dataLength = parcel.readInt();
byte[] data = new byte[dataLength];
@@ -274,7 +273,7 @@
if (parcel.dataAvail() >= Integer.SIZE) {
int status = parcel.readInt();
- navigationMessage.setStatus((short) status);
+ navigationMessage.setStatus(status);
} else {
navigationMessage.setStatus(STATUS_UNKNOWN);
}
@@ -328,7 +327,7 @@
}
private void initialize() {
- mType = MESSAGE_TYPE_UNKNOWN;
+ mType = TYPE_UNKNOWN;
mSvid = 0;
mMessageId = -1;
mSubmessageId = -1;
diff --git a/location/java/android/location/GnssNavigationMessageEvent.java b/location/java/android/location/GnssNavigationMessageEvent.java
index 19c82e9..0df730d 100644
--- a/location/java/android/location/GnssNavigationMessageEvent.java
+++ b/location/java/android/location/GnssNavigationMessageEvent.java
@@ -32,7 +32,7 @@
public final class GnssNavigationMessageEvent implements Parcelable {
/** The status of GPS measurements event. */
@Retention(RetentionPolicy.SOURCE)
- @IntDef({STATUS_NOT_SUPPORTED, STATUS_READY, STATUS_GPS_LOCATION_DISABLED})
+ @IntDef({STATUS_NOT_SUPPORTED, STATUS_READY, STATUS_GNSS_LOCATION_DISABLED})
public @interface GnssNavigationMessageStatus {}
/**
@@ -50,7 +50,7 @@
/**
* GPS provider or Location is disabled, updated will not be received until they are enabled.
*/
- public static final int STATUS_GPS_LOCATION_DISABLED = 2;
+ public static final int STATUS_GNSS_LOCATION_DISABLED = 2;
private final GnssNavigationMessage mNavigationMessage;
diff --git a/location/java/android/location/GnssStatus.java b/location/java/android/location/GnssStatus.java
index 06ce30c..2a42fc6 100644
--- a/location/java/android/location/GnssStatus.java
+++ b/location/java/android/location/GnssStatus.java
@@ -27,19 +27,19 @@
*/
public final class GnssStatus {
/** Unknown constellation type. */
- public static final byte CONSTELLATION_UNKNOWN = 0;
+ public static final int CONSTELLATION_UNKNOWN = 0;
/** Constellation type constant for GPS. */
- public static final byte CONSTELLATION_GPS = 1;
+ public static final int CONSTELLATION_GPS = 1;
/** Constellation type constant for SBAS. */
- public static final byte CONSTELLATION_SBAS = 2;
+ public static final int CONSTELLATION_SBAS = 2;
/** Constellation type constant for Glonass. */
- public static final byte CONSTELLATION_GLONASS = 3;
+ public static final int CONSTELLATION_GLONASS = 3;
/** Constellation type constant for QZSS. */
- public static final byte CONSTELLATION_QZSS = 4;
+ public static final int CONSTELLATION_QZSS = 4;
/** Constellation type constant for Beidou. */
- public static final byte CONSTELLATION_BEIDOU = 5;
+ public static final int CONSTELLATION_BEIDOU = 5;
/** Constellation type constant for Galileo. */
- public static final byte CONSTELLATION_GALILEO = 6;
+ public static final int CONSTELLATION_GALILEO = 6;
/** Constellation type. */
@Retention(RetentionPolicy.SOURCE)
@@ -66,16 +66,16 @@
/* These package private values are modified by the LocationManager class */
/* package */ int[] mSvidWithFlags;
- /* package */ float[] mSnrs;
+ /* package */ float[] mCn0DbHz;
/* package */ float[] mElevations;
/* package */ float[] mAzimuths;
/* package */ int mSvCount;
- GnssStatus(int svCount, int[] svidWithFlags, float[] snrs, float[] elevations,
+ GnssStatus(int svCount, int[] svidWithFlags, float[] cn0s, float[] elevations,
float[] azimuths) {
mSvCount = svCount;
mSvidWithFlags = svidWithFlags;
- mSnrs = snrs;
+ mCn0DbHz = cn0s;
mElevations = elevations;
mAzimuths = azimuths;
}
@@ -92,8 +92,8 @@
* @param satIndex the index of the satellite in the list.
*/
@ConstellationType
- public byte getConstellationType(int satIndex) {
- return (byte) ((mSvidWithFlags[satIndex] >> CONSTELLATION_TYPE_SHIFT_WIDTH)
+ public int getConstellationType(int satIndex) {
+ return ((mSvidWithFlags[satIndex] >> CONSTELLATION_TYPE_SHIFT_WIDTH)
& CONSTELLATION_TYPE_MASK);
}
@@ -109,15 +109,15 @@
* Retrieves the signal-noise ration of the satellite at the specified position.
* @param satIndex the index of the satellite in the list.
*/
- public float getSnr(int satIndex) {
- return mSnrs[satIndex];
+ public float getCn0DbHz(int satIndex) {
+ return mCn0DbHz[satIndex];
}
/**
* Retrieves the elevation of the satellite at the specified position.
* @param satIndex the index of the satellite in the list.
*/
- public float getElevation(int satIndex) {
+ public float getElevationDegrees(int satIndex) {
return 0f;
}
@@ -125,7 +125,7 @@
* Retrieves the azimuth the satellite at the specified position.
* @param satIndex the index of the satellite in the list.
*/
- public float getAzimuth(int satIndex) {
+ public float getAzimuthDegrees(int satIndex) {
return mAzimuths[satIndex];
}
diff --git a/location/java/android/location/GnssStatusCallback.java b/location/java/android/location/GnssStatusCallback.java
index b86171b..0d2955a 100644
--- a/location/java/android/location/GnssStatusCallback.java
+++ b/location/java/android/location/GnssStatusCallback.java
@@ -32,13 +32,13 @@
/**
* Called when the GNSS system has received its first fix since starting.
- * @param ttff the time from start to first fix.
+ * @param ttffMillis the time from start to first fix in milliseconds.
*/
- public void onFirstFix(int ttff) {}
+ public void onFirstFix(int ttffMillis) {}
/**
* Called periodically to report GNSS satellite status.
* @param status the current status of all satellites.
*/
public void onSatelliteStatusChanged(GnssStatus status) {}
-}
\ No newline at end of file
+}
diff --git a/location/java/android/location/GpsStatus.java b/location/java/android/location/GpsStatus.java
index 7b3dd7d..bc518f9 100644
--- a/location/java/android/location/GpsStatus.java
+++ b/location/java/android/location/GpsStatus.java
@@ -138,7 +138,7 @@
// For API-compat a public ctor() is not available
GpsStatus() {}
- private void setStatus(int svCount, int[] svidWithFlags, float[] snrs, float[] elevations,
+ private void setStatus(int svCount, int[] svidWithFlags, float[] cn0s, float[] elevations,
float[] azimuths) {
clearSatellites();
for (int i = 0; i < svCount; i++) {
@@ -158,7 +158,7 @@
}
satellite.mValid = true;
- satellite.mSnr = snrs[i];
+ satellite.mSnr = cn0s[i];
satellite.mElevation = elevations[i];
satellite.mAzimuth = azimuths[i];
satellite.mHasEphemeris =
@@ -179,7 +179,7 @@
*/
void setStatus(GnssStatus status, int timeToFirstFix) {
mTimeToFirstFix = timeToFirstFix;
- setStatus(status.mSvCount, status.mSvidWithFlags, status.mSnrs, status.mElevations,
+ setStatus(status.mSvCount, status.mSvidWithFlags, status.mCn0DbHz, status.mElevations,
status.mAzimuths);
}
diff --git a/location/java/android/location/IGnssStatusListener.aidl b/location/java/android/location/IGnssStatusListener.aidl
index 8c7d06e..d84614f 100644
--- a/location/java/android/location/IGnssStatusListener.aidl
+++ b/location/java/android/location/IGnssStatusListener.aidl
@@ -26,7 +26,7 @@
void onGnssStarted();
void onGnssStopped();
void onFirstFix(int ttff);
- void onSvStatusChanged(int svCount, in int[] svidWithFlags, in float[] snrs,
+ void onSvStatusChanged(int svCount, in int[] svidWithFlags, in float[] cn0s,
in float[] elevations, in float[] azimuths);
void onNmeaReceived(long timestamp, String nmea);
}
diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java
index 3cd47e7..28db099 100644
--- a/location/java/android/location/LocationManager.java
+++ b/location/java/android/location/LocationManager.java
@@ -1554,9 +1554,9 @@
@Override
public void onSvStatusChanged(int svCount, int[] prnWithFlags,
- float[] snrs, float[] elevations, float[] azimuths) {
+ float[] cn0s, float[] elevations, float[] azimuths) {
if (mGnssCallback != null) {
- mGnssStatus = new GnssStatus(svCount, prnWithFlags, snrs, elevations, azimuths);
+ mGnssStatus = new GnssStatus(svCount, prnWithFlags, cn0s, elevations, azimuths);
Message msg = Message.obtain();
msg.what = GpsStatus.GPS_EVENT_SATELLITE_STATUS;
@@ -1805,7 +1805,7 @@
/**
* No-op method to keep backward-compatibility.
- * Don't use it. Use {@link #registerGnssMeasurementCallback} instead.
+ * Don't use it. Use {@link #registerGnssMeasurementsCallback} instead.
* @hide
* @deprecated
*/
@@ -1822,8 +1822,8 @@
* @return {@code true} if the callback was added successfully, {@code false} otherwise.
*/
@RequiresPermission(ACCESS_FINE_LOCATION)
- public boolean registerGnssMeasurementCallback(GnssMeasurementsEvent.Callback callback) {
- return registerGnssMeasurementCallback(callback, null);
+ public boolean registerGnssMeasurementsCallback(GnssMeasurementsEvent.Callback callback) {
+ return registerGnssMeasurementsCallback(callback, null);
}
/**
@@ -1834,14 +1834,14 @@
* @return {@code true} if the callback was added successfully, {@code false} otherwise.
*/
@RequiresPermission(ACCESS_FINE_LOCATION)
- public boolean registerGnssMeasurementCallback(GnssMeasurementsEvent.Callback callback,
+ public boolean registerGnssMeasurementsCallback(GnssMeasurementsEvent.Callback callback,
Handler handler) {
return mGnssMeasurementCallbackTransport.add(callback, handler);
}
/**
* No-op method to keep backward-compatibility.
- * Don't use it. Use {@link #unregisterGnssMeasurementCallback} instead.
+ * Don't use it. Use {@link #unregisterGnssMeasurementsCallback} instead.
* @hide
* @deprecated
*/
@@ -1855,7 +1855,7 @@
*
* @param callback a {@link GnssMeasurementsEvent.Callback} object to remove.
*/
- public void unregisterGnssMeasurementCallback(GnssMeasurementsEvent.Callback callback) {
+ public void unregisterGnssMeasurementsCallback(GnssMeasurementsEvent.Callback callback) {
mGnssMeasurementCallbackTransport.remove(callback);
}
diff --git a/location/tests/locationtests/src/android/location/GpsStatusTest.java b/location/tests/locationtests/src/android/location/GpsStatusTest.java
index 4808faf..316e88d 100644
--- a/location/tests/locationtests/src/android/location/GpsStatusTest.java
+++ b/location/tests/locationtests/src/android/location/GpsStatusTest.java
@@ -40,7 +40,7 @@
private GpsStatus mStatus;
private int mCount;
private int[] mPrns;
- private float[] mSnrs;
+ private float[] mCn0s;
private float[] mElevations;
private float[] mAzimuth;
private int mEphemerisMask;
@@ -179,7 +179,7 @@
private void verifySatellites(GpsStatus status) {
verifySatelliteCount(status, mCount);
- verifySatellites(status, mCount, mPrns, mSnrs, mElevations, mAzimuth, mEphemerisMask,
+ verifySatellites(status, mCount, mPrns, mCn0s, mElevations, mAzimuth, mEphemerisMask,
mAlmanacMask, mUsedInFixMask);
}
@@ -187,7 +187,7 @@
GpsStatus status,
int count,
int[] prns,
- float[] snrs,
+ float[] cn0s,
float[] elevations,
float[] azimuth,
int ephemerisMask,
@@ -197,7 +197,7 @@
int prn = prns[i];
GpsSatellite satellite = getSatellite(status, prn);
assertNotNull(getSatelliteAssertInfo(i, prn, "non-null"), satellite);
- assertEquals(getSatelliteAssertInfo(i, prn, "Snr"), snrs[i], satellite.getSnr());
+ assertEquals(getSatelliteAssertInfo(i, prn, "Snr"), cn0s[i], satellite.getSnr());
assertEquals(
getSatelliteAssertInfo(i, prn, "Elevation"),
elevations[i],
@@ -247,7 +247,7 @@
}
private void setSatellites(GpsStatus status) throws Exception {
- set(status, mCount, mPrns, mSnrs, mElevations, mAzimuth, mEphemerisMask, mAlmanacMask,
+ set(status, mCount, mPrns, mCn0s, mElevations, mAzimuth, mEphemerisMask, mAlmanacMask,
mUsedInFixMask);
}
@@ -255,7 +255,7 @@
GpsStatus status,
int count,
int[] prns,
- float[] snrs,
+ float[] cn0s,
float[] elevations,
float[] azimuth,
int ephemerisMask,
@@ -279,7 +279,7 @@
status,
count,
prns,
- snrs,
+ cn0s,
elevations,
azimuth,
ephemerisMask,
@@ -333,7 +333,7 @@
if (!reusePrns) {
mPrns = generateIntArray(count);
}
- mSnrs = generateFloatArray(count);
+ mCn0s = generateFloatArray(count);
mElevations = generateFloatArray(count);
mAzimuth = generateFloatArray(count);
mEphemerisMask = generateMask(mPrns);
diff --git a/media/java/android/media/MediaFormat.java b/media/java/android/media/MediaFormat.java
index 646ab4e..a0e2481 100644
--- a/media/java/android/media/MediaFormat.java
+++ b/media/java/android/media/MediaFormat.java
@@ -644,6 +644,21 @@
/** Full range. Y, Cr and Cb component values range from 0 to 255 for 8-bit content. */
public static final int COLOR_RANGE_FULL = 1;
+ /**
+ * A key describing a unique ID for the content of a media track.
+ *
+ * <p>This key is used by {@link MediaExtractor}. Some extractors provide multiple encodings
+ * of the same track (e.g. float audio tracks for FLAC and WAV may be expressed as two
+ * tracks via MediaExtractor: a normal PCM track for backward compatibility, and a float PCM
+ * track for added fidelity. Similarly, Dolby Vision extractor may provide a baseline SDR
+ * version of a DV track.) This key can be used to identify which MediaExtractor tracks refer
+ * to the same underlying content.
+ * </p>
+ *
+ * The associated value is an integer.
+ */
+ public static final String KEY_TRACK_ID = "track-id";
+
/* package private */ MediaFormat(Map<String, Object> map) {
mMap = map;
}
diff --git a/media/java/android/media/MediaMetadata.java b/media/java/android/media/MediaMetadata.java
index 39bcef5..722605f 100644
--- a/media/java/android/media/MediaMetadata.java
+++ b/media/java/android/media/MediaMetadata.java
@@ -16,6 +16,7 @@
package android.media;
import android.annotation.NonNull;
+import android.annotation.StringDef;
import android.content.ContentResolver;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
@@ -30,6 +31,8 @@
import android.util.Log;
import android.util.SparseArray;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.util.Set;
/**
@@ -39,6 +42,40 @@
private static final String TAG = "MediaMetadata";
/**
+ * @hide
+ */
+ @StringDef({METADATA_KEY_TITLE, METADATA_KEY_ARTIST, METADATA_KEY_ALBUM, METADATA_KEY_AUTHOR,
+ METADATA_KEY_WRITER, METADATA_KEY_COMPOSER, METADATA_KEY_COMPILATION,
+ METADATA_KEY_DATE, METADATA_KEY_GENRE, METADATA_KEY_ALBUM_ARTIST, METADATA_KEY_ART_URI,
+ METADATA_KEY_ALBUM_ART_URI, METADATA_KEY_DISPLAY_TITLE, METADATA_KEY_DISPLAY_SUBTITLE,
+ METADATA_KEY_DISPLAY_DESCRIPTION, METADATA_KEY_DISPLAY_ICON_URI,
+ METADATA_KEY_MEDIA_ID})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface TextKey {}
+
+ /**
+ * @hide
+ */
+ @StringDef({METADATA_KEY_DURATION, METADATA_KEY_YEAR, METADATA_KEY_TRACK_NUMBER,
+ METADATA_KEY_NUM_TRACKS, METADATA_KEY_DISC_NUMBER})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface LongKey {}
+
+ /**
+ * @hide
+ */
+ @StringDef({METADATA_KEY_ART, METADATA_KEY_ALBUM_ART, METADATA_KEY_DISPLAY_ICON})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface BitmapKey {}
+
+ /**
+ * @hide
+ */
+ @StringDef({METADATA_KEY_USER_RATING, METADATA_KEY_RATING})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface RatingKey {}
+
+ /**
* The title of the media.
*/
public static final String METADATA_KEY_TITLE = "android.media.metadata.TITLE";
@@ -232,7 +269,7 @@
*/
public static final String METADATA_KEY_MEDIA_ID = "android.media.metadata.MEDIA_ID";
- private static final String[] PREFERRED_DESCRIPTION_ORDER = {
+ private static final @TextKey String[] PREFERRED_DESCRIPTION_ORDER = {
METADATA_KEY_TITLE,
METADATA_KEY_ARTIST,
METADATA_KEY_ALBUM,
@@ -242,13 +279,13 @@
METADATA_KEY_COMPOSER
};
- private static final String[] PREFERRED_BITMAP_ORDER = {
+ private static final @BitmapKey String[] PREFERRED_BITMAP_ORDER = {
METADATA_KEY_DISPLAY_ICON,
METADATA_KEY_ART,
METADATA_KEY_ALBUM_ART
};
- private static final String[] PREFERRED_URI_ORDER = {
+ private static final @TextKey String[] PREFERRED_URI_ORDER = {
METADATA_KEY_DISPLAY_ICON_URI,
METADATA_KEY_ART_URI,
METADATA_KEY_ALBUM_ART_URI
@@ -349,7 +386,7 @@
* @param key The key the value is stored under
* @return a CharSequence value, or null
*/
- public CharSequence getText(String key) {
+ public CharSequence getText(@TextKey String key) {
return mBundle.getCharSequence(key);
}
@@ -362,7 +399,7 @@
* @param key The key the value is stored under
* @return a String value, or null
*/
- public String getString(String key) {
+ public String getString(@TextKey String key) {
CharSequence text = getText(key);
if (text != null) {
return text.toString();
@@ -377,7 +414,7 @@
* @param key The key the value is stored under
* @return a long value
*/
- public long getLong(String key) {
+ public long getLong(@LongKey String key) {
return mBundle.getLong(key, 0);
}
@@ -388,7 +425,7 @@
* @param key The key the value is stored under
* @return A {@link Rating} or null
*/
- public Rating getRating(String key) {
+ public Rating getRating(@RatingKey String key) {
Rating rating = null;
try {
rating = mBundle.getParcelable(key);
@@ -406,7 +443,7 @@
* @param key The key the value is stored under
* @return A {@link Bitmap} or null
*/
- public Bitmap getBitmap(String key) {
+ public Bitmap getBitmap(@BitmapKey String key) {
Bitmap bmp = null;
try {
bmp = mBundle.getParcelable(key);
@@ -612,7 +649,7 @@
* @param value The CharSequence value to store
* @return The Builder to allow chaining
*/
- public Builder putText(String key, CharSequence value) {
+ public Builder putText(@TextKey String key, CharSequence value) {
if (METADATA_KEYS_TYPE.containsKey(key)) {
if (METADATA_KEYS_TYPE.get(key) != METADATA_TYPE_TEXT) {
throw new IllegalArgumentException("The " + key
@@ -654,7 +691,7 @@
* @param value The String value to store
* @return The Builder to allow chaining
*/
- public Builder putString(String key, String value) {
+ public Builder putString(@TextKey String key, String value) {
if (METADATA_KEYS_TYPE.containsKey(key)) {
if (METADATA_KEYS_TYPE.get(key) != METADATA_TYPE_TEXT) {
throw new IllegalArgumentException("The " + key
@@ -681,7 +718,7 @@
* @param value The long value to store
* @return The Builder to allow chaining
*/
- public Builder putLong(String key, long value) {
+ public Builder putLong(@LongKey String key, long value) {
if (METADATA_KEYS_TYPE.containsKey(key)) {
if (METADATA_KEYS_TYPE.get(key) != METADATA_TYPE_LONG) {
throw new IllegalArgumentException("The " + key
@@ -705,7 +742,7 @@
* @param value The Rating value to store
* @return The Builder to allow chaining
*/
- public Builder putRating(String key, Rating value) {
+ public Builder putRating(@RatingKey String key, Rating value) {
if (METADATA_KEYS_TYPE.containsKey(key)) {
if (METADATA_KEYS_TYPE.get(key) != METADATA_TYPE_RATING) {
throw new IllegalArgumentException("The " + key
@@ -734,7 +771,7 @@
* @param value The Bitmap to store
* @return The Builder to allow chaining
*/
- public Builder putBitmap(String key, Bitmap value) {
+ public Builder putBitmap(@BitmapKey String key, Bitmap value) {
if (METADATA_KEYS_TYPE.containsKey(key)) {
if (METADATA_KEYS_TYPE.get(key) != METADATA_TYPE_BITMAP) {
throw new IllegalArgumentException("The " + key
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index adf8551..b78869e 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -2845,13 +2845,17 @@
MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, MEDIA_ERROR_UNSUPPORTED, null);
sendMessage(msg2);
}
- if (mOnPreparedListener != null)
- mOnPreparedListener.onPrepared(mMediaPlayer);
+ OnPreparedListener onPreparedListener = mOnPreparedListener;
+ if (onPreparedListener != null)
+ onPreparedListener.onPrepared(mMediaPlayer);
return;
case MEDIA_PLAYBACK_COMPLETE:
- if (mOnCompletionListener != null)
- mOnCompletionListener.onCompletion(mMediaPlayer);
+ {
+ OnCompletionListener onCompletionListener = mOnCompletionListener;
+ if (onCompletionListener != null)
+ onCompletionListener.onCompletion(mMediaPlayer);
+ }
stayAwake(false);
return;
@@ -2875,13 +2879,15 @@
break;
case MEDIA_BUFFERING_UPDATE:
- if (mOnBufferingUpdateListener != null)
- mOnBufferingUpdateListener.onBufferingUpdate(mMediaPlayer, msg.arg1);
+ OnBufferingUpdateListener onBufferingUpdateListener = mOnBufferingUpdateListener;
+ if (onBufferingUpdateListener != null)
+ onBufferingUpdateListener.onBufferingUpdate(mMediaPlayer, msg.arg1);
return;
case MEDIA_SEEK_COMPLETE:
- if (mOnSeekCompleteListener != null) {
- mOnSeekCompleteListener.onSeekComplete(mMediaPlayer);
+ OnSeekCompleteListener onSeekCompleteListener = mOnSeekCompleteListener;
+ if (onSeekCompleteListener != null) {
+ onSeekCompleteListener.onSeekComplete(mMediaPlayer);
}
// fall through
@@ -2895,8 +2901,9 @@
return;
case MEDIA_SET_VIDEO_SIZE:
- if (mOnVideoSizeChangedListener != null) {
- mOnVideoSizeChangedListener.onVideoSizeChanged(
+ OnVideoSizeChangedListener onVideoSizeChangedListener = mOnVideoSizeChangedListener;
+ if (onVideoSizeChangedListener != null) {
+ onVideoSizeChangedListener.onVideoSizeChanged(
mMediaPlayer, msg.arg1, msg.arg2);
}
return;
@@ -2904,11 +2911,15 @@
case MEDIA_ERROR:
Log.e(TAG, "Error (" + msg.arg1 + "," + msg.arg2 + ")");
boolean error_was_handled = false;
- if (mOnErrorListener != null) {
- error_was_handled = mOnErrorListener.onError(mMediaPlayer, msg.arg1, msg.arg2);
+ OnErrorListener onErrorListener = mOnErrorListener;
+ if (onErrorListener != null) {
+ error_was_handled = onErrorListener.onError(mMediaPlayer, msg.arg1, msg.arg2);
}
- if (mOnCompletionListener != null && ! error_was_handled) {
- mOnCompletionListener.onCompletion(mMediaPlayer);
+ {
+ OnCompletionListener onCompletionListener = mOnCompletionListener;
+ if (onCompletionListener != null && ! error_was_handled) {
+ onCompletionListener.onCompletion(mMediaPlayer);
+ }
}
stayAwake(false);
return;
@@ -2944,47 +2955,52 @@
break;
}
- if (mOnInfoListener != null) {
- mOnInfoListener.onInfo(mMediaPlayer, msg.arg1, msg.arg2);
+ OnInfoListener onInfoListener = mOnInfoListener;
+ if (onInfoListener != null) {
+ onInfoListener.onInfo(mMediaPlayer, msg.arg1, msg.arg2);
}
// No real default action so far.
return;
case MEDIA_TIMED_TEXT:
- if (mOnTimedTextListener == null)
+ OnTimedTextListener onTimedTextListener = mOnTimedTextListener;
+ if (onTimedTextListener == null)
return;
if (msg.obj == null) {
- mOnTimedTextListener.onTimedText(mMediaPlayer, null);
+ onTimedTextListener.onTimedText(mMediaPlayer, null);
} else {
if (msg.obj instanceof Parcel) {
Parcel parcel = (Parcel)msg.obj;
TimedText text = new TimedText(parcel);
parcel.recycle();
- mOnTimedTextListener.onTimedText(mMediaPlayer, text);
+ onTimedTextListener.onTimedText(mMediaPlayer, text);
}
}
return;
case MEDIA_SUBTITLE_DATA:
- if (mOnSubtitleDataListener == null) {
+ OnSubtitleDataListener onSubtitleDataListener = mOnSubtitleDataListener;
+ if (onSubtitleDataListener == null) {
return;
}
if (msg.obj instanceof Parcel) {
Parcel parcel = (Parcel) msg.obj;
SubtitleData data = new SubtitleData(parcel);
parcel.recycle();
- mOnSubtitleDataListener.onSubtitleData(mMediaPlayer, data);
+ onSubtitleDataListener.onSubtitleData(mMediaPlayer, data);
}
return;
case MEDIA_META_DATA:
- if (mOnTimedMetaDataAvailableListener == null) {
+ OnTimedMetaDataAvailableListener onTimedMetaDataAvailableListener =
+ mOnTimedMetaDataAvailableListener;
+ if (onTimedMetaDataAvailableListener == null) {
return;
}
if (msg.obj instanceof Parcel) {
Parcel parcel = (Parcel) msg.obj;
TimedMetaData data = TimedMetaData.createTimedMetaDataFromParcel(parcel);
parcel.recycle();
- mOnTimedMetaDataAvailableListener.onTimedMetaDataAvailable(mMediaPlayer, data);
+ onTimedMetaDataAvailableListener.onTimedMetaDataAvailable(mMediaPlayer, data);
}
return;
diff --git a/media/java/android/media/MediaRouter.java b/media/java/android/media/MediaRouter.java
index bcc2b406..d8e0d6d 100644
--- a/media/java/android/media/MediaRouter.java
+++ b/media/java/android/media/MediaRouter.java
@@ -1547,18 +1547,30 @@
private Object mTag;
+ /** @hide */
+ @IntDef({PLAYBACK_TYPE_LOCAL, PLAYBACK_TYPE_REMOTE})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface PlaybackType {}
+
/**
* The default playback type, "local", indicating the presentation of the media is happening
* on the same device (e.g. a phone, a tablet) as where it is controlled from.
* @see #getPlaybackType()
*/
public final static int PLAYBACK_TYPE_LOCAL = 0;
+
/**
* A playback type indicating the presentation of the media is happening on
* a different device (i.e. the remote device) than where it is controlled from.
* @see #getPlaybackType()
*/
public final static int PLAYBACK_TYPE_REMOTE = 1;
+
+ /** @hide */
+ @IntDef({PLAYBACK_VOLUME_FIXED,PLAYBACK_VOLUME_VARIABLE})
+ @Retention(RetentionPolicy.SOURCE)
+ private @interface PlaybackVolume {}
+
/**
* Playback information indicating the playback volume is fixed, i.e. it cannot be
* controlled from this object. An example of fixed playback volume is a remote player,
@@ -1783,6 +1795,7 @@
* @return the type of playback associated with this route
* @see UserRouteInfo#setPlaybackType(int)
*/
+ @PlaybackType
public int getPlaybackType() {
return mPlaybackType;
}
@@ -1874,6 +1887,7 @@
* @return how volume is handling on the route
* @see UserRouteInfo#setVolumeHandling(int)
*/
+ @PlaybackVolume
public int getVolumeHandling() {
return mVolumeHandling;
}
@@ -2164,7 +2178,7 @@
* ({@link RouteInfo#PLAYBACK_TYPE_REMOTE}).
* @param type
*/
- public void setPlaybackType(int type) {
+ public void setPlaybackType(@RouteInfo.PlaybackType int type) {
if (mPlaybackType != type) {
mPlaybackType = type;
configureSessionVolume();
@@ -2177,7 +2191,7 @@
* ({@link RouteInfo#PLAYBACK_VOLUME_VARIABLE}).
* @param volumeHandling
*/
- public void setVolumeHandling(int volumeHandling) {
+ public void setVolumeHandling(@RouteInfo.PlaybackVolume int volumeHandling) {
if (mVolumeHandling != volumeHandling) {
mVolumeHandling = volumeHandling;
configureSessionVolume();
@@ -2268,7 +2282,8 @@
return;
}
if (mPlaybackType == RemoteControlClient.PLAYBACK_TYPE_REMOTE) {
- int volumeControl = VolumeProvider.VOLUME_CONTROL_FIXED;
+ @VolumeProvider.ControlType int volumeControl =
+ VolumeProvider.VOLUME_CONTROL_FIXED;
switch (mVolumeHandling) {
case RemoteControlClient.PLAYBACK_VOLUME_VARIABLE:
volumeControl = VolumeProvider.VOLUME_CONTROL_ABSOLUTE;
@@ -2294,7 +2309,8 @@
class SessionVolumeProvider extends VolumeProvider {
- public SessionVolumeProvider(int volumeControl, int maxVolume, int currentVolume) {
+ public SessionVolumeProvider(@VolumeProvider.ControlType int volumeControl,
+ int maxVolume, int currentVolume) {
super(volumeControl, maxVolume, currentVolume);
}
diff --git a/media/java/android/media/Rating.java b/media/java/android/media/Rating.java
index a518bb4..04d5364f 100644
--- a/media/java/android/media/Rating.java
+++ b/media/java/android/media/Rating.java
@@ -16,10 +16,14 @@
package android.media;
+import android.annotation.IntDef;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.Log;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
/**
* A class to encapsulate rating information used as content metadata.
* A rating is defined by its rating style (see {@link #RATING_HEART},
@@ -32,6 +36,21 @@
private final static String TAG = "Rating";
/**
+ * @hide
+ */
+ @IntDef({RATING_NONE, RATING_HEART, RATING_THUMB_UP_DOWN, RATING_3_STARS, RATING_4_STARS,
+ RATING_5_STARS, RATING_PERCENTAGE})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface Style {}
+
+ /**
+ * @hide
+ */
+ @IntDef({RATING_3_STARS, RATING_4_STARS, RATING_5_STARS})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface StarStyle {}
+
+ /**
* Indicates a rating style is not supported. A Rating will never have this
* type, but can be used by other classes to indicate they do not support
* Rating.
@@ -75,7 +94,7 @@
private final float mRatingValue;
- private Rating(int ratingStyle, float rating) {
+ private Rating(@Style int ratingStyle, float rating) {
mRatingStyle = ratingStyle;
mRatingValue = rating;
}
@@ -124,7 +143,7 @@
* or {@link #RATING_PERCENTAGE}.
* @return null if an invalid rating style is passed, a new Rating instance otherwise.
*/
- public static Rating newUnratedRating(int ratingStyle) {
+ public static Rating newUnratedRating(@Style int ratingStyle) {
switch(ratingStyle) {
case RATING_HEART:
case RATING_THUMB_UP_DOWN:
@@ -172,7 +191,7 @@
* @return null if the rating style is invalid, or the rating is out of range,
* a new Rating instance otherwise.
*/
- public static Rating newStarRating(int starRatingStyle, float starRating) {
+ public static Rating newStarRating(@StarStyle int starRatingStyle, float starRating) {
float maxRating = -1.0f;
switch(starRatingStyle) {
case RATING_3_STARS:
@@ -225,6 +244,7 @@
* {@link #RATING_3_STARS}, {@link #RATING_4_STARS}, {@link #RATING_5_STARS},
* or {@link #RATING_PERCENTAGE}.
*/
+ @Style
public int getRatingStyle() {
return mRatingStyle;
}
@@ -285,4 +305,4 @@
return mRatingValue;
}
}
-}
\ No newline at end of file
+}
diff --git a/media/java/android/media/VolumeProvider.java b/media/java/android/media/VolumeProvider.java
index 5d1e004..1c017c5 100644
--- a/media/java/android/media/VolumeProvider.java
+++ b/media/java/android/media/VolumeProvider.java
@@ -15,8 +15,12 @@
*/
package android.media;
+import android.annotation.IntDef;
import android.media.session.MediaSession;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
/**
* Handles requests to adjust or set the volume on a session. This is also used
* to push volume updates back to the session. The provider must call
@@ -26,6 +30,14 @@
* {@link MediaSession#setPlaybackToRemote}.
*/
public abstract class VolumeProvider {
+
+ /**
+ * @hide
+ */
+ @IntDef({VOLUME_CONTROL_FIXED, VOLUME_CONTROL_RELATIVE, VOLUME_CONTROL_ABSOLUTE})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface ControlType {}
+
/**
* The volume is fixed and can not be modified. Requests to change volume
* should be ignored.
@@ -61,7 +73,7 @@
* @param maxVolume The maximum allowed volume.
* @param currentVolume The current volume on the output.
*/
- public VolumeProvider(int volumeControl, int maxVolume, int currentVolume) {
+ public VolumeProvider(@ControlType int volumeControl, int maxVolume, int currentVolume) {
mControlType = volumeControl;
mMaxVolume = maxVolume;
mCurrentVolume = currentVolume;
@@ -72,6 +84,7 @@
*
* @return The volume control type for this volume provider
*/
+ @ControlType
public final int getVolumeControl() {
return mControlType;
}
@@ -145,4 +158,4 @@
public static abstract class Callback {
public abstract void onVolumeChanged(VolumeProvider volumeProvider);
}
-}
\ No newline at end of file
+}
diff --git a/media/java/android/media/browse/MediaBrowser.java b/media/java/android/media/browse/MediaBrowser.java
index 9e67c15..ada0e2c 100644
--- a/media/java/android/media/browse/MediaBrowser.java
+++ b/media/java/android/media/browse/MediaBrowser.java
@@ -633,7 +633,6 @@
return;
}
- List<MediaItem> data = list == null ? null : list.getList();
if (DBG) {
Log.d(TAG, "onLoadChildren for " + mServiceComponent + " id=" + parentId);
}
@@ -644,10 +643,19 @@
// Tell the app.
SubscriptionCallback subscriptionCallback = subscription.getCallback(options);
if (subscriptionCallback != null) {
+ List<MediaItem> data = list == null ? null : list.getList();
if (options == null) {
- subscriptionCallback.onChildrenLoaded(parentId, data);
+ if (data == null) {
+ subscriptionCallback.onError(parentId);
+ } else {
+ subscriptionCallback.onChildrenLoaded(parentId, data);
+ }
} else {
- subscriptionCallback.onChildrenLoaded(parentId, data, options);
+ if (data == null) {
+ subscriptionCallback.onError(parentId, options);
+ } else {
+ subscriptionCallback.onChildrenLoaded(parentId, data, options);
+ }
}
return;
}
@@ -848,21 +856,21 @@
* Called when the list of children is loaded or updated.
*
* @param parentId The media id of the parent media item.
- * @param children The children which were loaded, or null if the id is invalid.
+ * @param children The children which were loaded.
*/
- public void onChildrenLoaded(@NonNull String parentId, List<MediaItem> children) {
+ public void onChildrenLoaded(@NonNull String parentId, @NonNull List<MediaItem> children) {
}
/**
* Called when the list of children is loaded or updated.
*
* @param parentId The media id of the parent media item.
- * @param children The children which were loaded, or null if the id is invalid.
+ * @param children The children which were loaded.
* @param options A bundle of service-specific arguments sent to the media
* browse service. The contents of this bundle may affect the
* information returned when browsing.
*/
- public void onChildrenLoaded(@NonNull String parentId, List<MediaItem> children,
+ public void onChildrenLoaded(@NonNull String parentId, @NonNull List<MediaItem> children,
@NonNull Bundle options) {
}
diff --git a/media/java/android/media/midi/MidiManager.java b/media/java/android/media/midi/MidiManager.java
index 266b0d9..07c8ae8 100644
--- a/media/java/android/media/midi/MidiManager.java
+++ b/media/java/android/media/midi/MidiManager.java
@@ -186,8 +186,7 @@
try {
mService.registerListener(mToken, deviceListener);
} catch (RemoteException e) {
- Log.e(TAG, "RemoteException in registerDeviceListener");
- return;
+ throw e.rethrowFromSystemServer();
}
mDeviceListeners.put(callback, deviceListener);
}
@@ -203,7 +202,7 @@
try {
mService.unregisterListener(mToken, deviceListener);
} catch (RemoteException e) {
- Log.e(TAG, "RemoteException in unregisterDeviceListener");
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -217,8 +216,7 @@
try {
return mService.getDevices();
} catch (RemoteException e) {
- Log.e(TAG, "RemoteException in getDevices");
- return new MidiDeviceInfo[0];
+ throw e.rethrowFromSystemServer();
}
}
@@ -267,7 +265,7 @@
try {
mService.openDevice(mToken, deviceInfo, callback);
} catch (RemoteException e) {
- Log.e(TAG, "RemoteException in openDevice");
+ throw e.rethrowFromSystemServer();
}
}
@@ -306,7 +304,7 @@
try {
mService.openBluetoothDevice(mToken, bluetoothDevice, callback);
} catch (RemoteException e) {
- Log.e(TAG, "RemoteException in openDevice");
+ throw e.rethrowFromSystemServer();
}
}
@@ -326,8 +324,7 @@
}
return server;
} catch (RemoteException e) {
- Log.e(TAG, "RemoteException in createVirtualDevice");
- return null;
+ throw e.rethrowFromSystemServer();
}
}
}
diff --git a/media/java/android/media/session/MediaSession.java b/media/java/android/media/session/MediaSession.java
index 0bd1713..7f9653d 100644
--- a/media/java/android/media/session/MediaSession.java
+++ b/media/java/android/media/session/MediaSession.java
@@ -469,7 +469,7 @@
* <li>{@link Rating#RATING_THUMB_UP_DOWN}</li>
* </ul>
*/
- public void setRatingType(int type) {
+ public void setRatingType(@Rating.Style int type) {
try {
mBinder.setRatingType(type);
} catch (RemoteException e) {
diff --git a/media/java/android/media/session/PlaybackState.java b/media/java/android/media/session/PlaybackState.java
index 1485cd7..8283c8b 100644
--- a/media/java/android/media/session/PlaybackState.java
+++ b/media/java/android/media/session/PlaybackState.java
@@ -16,6 +16,7 @@
package android.media.session;
import android.annotation.DrawableRes;
+import android.annotation.IntDef;
import android.annotation.Nullable;
import android.media.RemoteControlClient;
import android.os.Bundle;
@@ -26,6 +27,9 @@
import java.util.ArrayList;
import java.util.List;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
/**
* Playback state for a {@link MediaSession}. This includes a state like
* {@link PlaybackState#STATE_PLAYING}, the current playback position,
@@ -35,6 +39,17 @@
private static final String TAG = "PlaybackState";
/**
+ * @hide
+ */
+ @IntDef(flag=true, value={ACTION_STOP, ACTION_PAUSE, ACTION_PLAY, ACTION_REWIND,
+ ACTION_SKIP_TO_PREVIOUS, ACTION_SKIP_TO_NEXT, ACTION_FAST_FORWARD, ACTION_SET_RATING,
+ ACTION_SEEK_TO, ACTION_PLAY_PAUSE, ACTION_PLAY_FROM_MEDIA_ID, ACTION_PLAY_FROM_SEARCH,
+ ACTION_SKIP_TO_QUEUE_ITEM, ACTION_PLAY_FROM_URI, ACTION_PREPARE,
+ ACTION_PREPARE_FROM_MEDIA_ID, ACTION_PREPARE_FROM_SEARCH, ACTION_PREPARE_FROM_URI})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface Actions {}
+
+ /**
* Indicates this session supports the stop command.
*
* @see Builder#setActions(long)
@@ -161,6 +176,15 @@
public static final long ACTION_PREPARE_FROM_URI = 1 << 17;
/**
+ * @hide
+ */
+ @IntDef({STATE_NONE, STATE_STOPPED, STATE_PAUSED, STATE_PLAYING, STATE_FAST_FORWARDING,
+ STATE_REWINDING, STATE_BUFFERING, STATE_ERROR, STATE_CONNECTING,
+ STATE_SKIPPING_TO_PREVIOUS, STATE_SKIPPING_TO_NEXT, STATE_SKIPPING_TO_QUEUE_ITEM})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface State {}
+
+ /**
* This is the default playback state and indicates that no media has been
* added yet, or the performer has been reset and has no content to play.
*
@@ -349,9 +373,11 @@
* <li> {@link PlaybackState#STATE_SKIPPING_TO_QUEUE_ITEM}</li>
* </ul>
*/
+ @State
public int getState() {
return mState;
}
+
/**
* Get the current playback position in ms.
*/
@@ -403,6 +429,7 @@
* <li> {@link PlaybackState#ACTION_PREPARE_FROM_URI}</li>
* </ul>
*/
+ @Actions
public long getActions() {
return mActions;
}
@@ -866,7 +893,8 @@
* timebase that the position was updated at.
* @return this
*/
- public Builder setState(int state, long position, float playbackSpeed, long updateTime) {
+ public Builder setState(@State int state, long position, float playbackSpeed,
+ long updateTime) {
mState = state;
mPosition = position;
mUpdateTime = updateTime;
@@ -907,7 +935,7 @@
* normal playback.
* @return this
*/
- public Builder setState(int state, long position, float playbackSpeed) {
+ public Builder setState(@State int state, long position, float playbackSpeed) {
return setState(state, position, playbackSpeed, SystemClock.elapsedRealtime());
}
@@ -938,7 +966,7 @@
* @param actions The set of actions allowed.
* @return this
*/
- public Builder setActions(long actions) {
+ public Builder setActions(@Actions long actions) {
mActions = actions;
return this;
}
diff --git a/media/java/android/media/soundtrigger/SoundTriggerManager.java b/media/java/android/media/soundtrigger/SoundTriggerManager.java
index 4fd3310..fdd7fc2 100644
--- a/media/java/android/media/soundtrigger/SoundTriggerManager.java
+++ b/media/java/android/media/soundtrigger/SoundTriggerManager.java
@@ -69,6 +69,7 @@
try {
mSoundTriggerService.updateSoundModel(model.getGenericSoundModel());
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
@@ -81,7 +82,7 @@
return new Model(mSoundTriggerService.getSoundModel(
new ParcelUuid(soundModelId)));
} catch (RemoteException e) {
- return null;
+ throw e.rethrowFromSystemServer();
}
}
@@ -92,6 +93,7 @@
try {
mSoundTriggerService.deleteSoundModel(new ParcelUuid(soundModelId));
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
diff --git a/media/java/android/media/tv/TvInputManager.java b/media/java/android/media/tv/TvInputManager.java
index 59dfbee..0b0306c 100644
--- a/media/java/android/media/tv/TvInputManager.java
+++ b/media/java/android/media/tv/TvInputManager.java
@@ -1111,7 +1111,7 @@
}
}
} catch (RemoteException e) {
- Log.e(TAG, "TvInputManager initialization failed", e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1124,7 +1124,7 @@
try {
return mService.getTvInputList(mUserId);
} catch (RemoteException e) {
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1140,7 +1140,7 @@
try {
return mService.getTvInputInfo(inputId, mUserId);
} catch (RemoteException e) {
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1157,7 +1157,7 @@
try {
mService.updateTvInputInfo(inputInfo, mUserId);
} catch (RemoteException e) {
- throw new RuntimeException("Error trying to update " + inputInfo, e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1228,7 +1228,7 @@
try {
return mService.isParentalControlsEnabled(mUserId);
} catch (RemoteException e) {
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1245,7 +1245,7 @@
try {
mService.setParentalControlsEnabled(enabled, mUserId);
} catch (RemoteException e) {
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1260,7 +1260,7 @@
try {
return mService.isRatingBlocked(rating.flattenToString(), mUserId);
} catch (RemoteException e) {
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1279,7 +1279,7 @@
}
return ratings;
} catch (RemoteException e) {
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1297,7 +1297,7 @@
try {
mService.addBlockedRating(rating.flattenToString(), mUserId);
} catch (RemoteException e) {
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1315,7 +1315,7 @@
try {
mService.removeBlockedRating(rating.flattenToString(), mUserId);
} catch (RemoteException e) {
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1328,7 +1328,7 @@
try {
return mService.getTvContentRatingSystemList(mUserId);
} catch (RemoteException e) {
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1378,7 +1378,7 @@
try {
mService.createSession(mClient, inputId, isRecordingSession, seq, mUserId);
} catch (RemoteException e) {
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -1402,7 +1402,7 @@
try {
return mService.getAvailableTvStreamConfigList(inputId, mUserId);
} catch (RemoteException e) {
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1420,7 +1420,7 @@
try {
return mService.captureFrame(inputId, surface, config, mUserId);
} catch (RemoteException e) {
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1434,7 +1434,7 @@
try {
return mService.isSingleSessionActive(mUserId);
} catch (RemoteException e) {
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1448,7 +1448,7 @@
try {
return mService.getHardwareList();
} catch (RemoteException e) {
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1478,7 +1478,7 @@
}
}, info, mUserId));
} catch (RemoteException e) {
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1492,7 +1492,7 @@
try {
mService.releaseTvInputHardware(deviceId, hardware.getInterface(), mUserId);
} catch (RemoteException e) {
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1506,7 +1506,7 @@
try {
return mService.getDvbDeviceList();
} catch (RemoteException e) {
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1529,7 +1529,7 @@
}
return mService.openDvbDevice(info, device);
} catch (RemoteException e) {
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1600,7 +1600,7 @@
try {
mService.releaseSession(mToken, mUserId);
} catch (RemoteException e) {
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
releaseInternal();
@@ -1620,7 +1620,7 @@
try {
mService.setMainSession(mToken, mUserId);
} catch (RemoteException e) {
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1638,7 +1638,7 @@
try {
mService.setSurface(mToken, surface, mUserId);
} catch (RemoteException e) {
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1660,7 +1660,7 @@
try {
mService.dispatchSurfaceChanged(mToken, format, width, height, mUserId);
} catch (RemoteException e) {
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1681,7 +1681,7 @@
}
mService.setVolume(mToken, volume, mUserId);
} catch (RemoteException e) {
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1721,7 +1721,7 @@
try {
mService.tune(mToken, channelUri, params, mUserId);
} catch (RemoteException e) {
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1738,7 +1738,7 @@
try {
mService.setCaptionEnabled(mToken, enabled, mUserId);
} catch (RemoteException e) {
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1780,7 +1780,7 @@
try {
mService.selectTrack(mToken, type, trackId, mUserId);
} catch (RemoteException e) {
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1928,7 +1928,7 @@
try {
mService.timeShiftPlay(mToken, recordedProgramUri, mUserId);
} catch (RemoteException e) {
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1943,7 +1943,7 @@
try {
mService.timeShiftPause(mToken, mUserId);
} catch (RemoteException e) {
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1958,7 +1958,7 @@
try {
mService.timeShiftResume(mToken, mUserId);
} catch (RemoteException e) {
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1979,7 +1979,7 @@
try {
mService.timeShiftSeekTo(mToken, timeMs, mUserId);
} catch (RemoteException e) {
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -1996,7 +1996,7 @@
try {
mService.timeShiftSetPlaybackParams(mToken, params, mUserId);
} catch (RemoteException e) {
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -2013,7 +2013,7 @@
try {
mService.timeShiftEnablePositionTracking(mToken, enable, mUserId);
} catch (RemoteException e) {
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -2031,7 +2031,7 @@
try {
mService.startRecording(mToken, programHint, mUserId);
} catch (RemoteException e) {
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -2046,7 +2046,7 @@
try {
mService.stopRecording(mToken, mUserId);
} catch (RemoteException e) {
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -2069,7 +2069,7 @@
try {
mService.sendAppPrivateCommand(mToken, action, data, mUserId);
} catch (RemoteException e) {
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -2097,7 +2097,7 @@
try {
mService.createOverlayView(mToken, view.getWindowToken(), frame, mUserId);
} catch (RemoteException e) {
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -2115,7 +2115,7 @@
try {
mService.relayoutOverlayView(mToken, frame, mUserId);
} catch (RemoteException e) {
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -2130,7 +2130,7 @@
try {
mService.removeOverlayView(mToken, mUserId);
} catch (RemoteException e) {
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -2146,7 +2146,7 @@
try {
mService.unblockContent(mToken, unblockedRating.flattenToString(), mUserId);
} catch (RemoteException e) {
- throw new RuntimeException(e);
+ throw e.rethrowFromSystemServer();
}
}
diff --git a/media/java/android/service/media/MediaBrowserService.java b/media/java/android/service/media/MediaBrowserService.java
index 480acd9..b5ea2a0 100644
--- a/media/java/android/service/media/MediaBrowserService.java
+++ b/media/java/android/service/media/MediaBrowserService.java
@@ -45,6 +45,7 @@
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.HashMap;
import java.util.List;
@@ -120,8 +121,8 @@
* they are done. If more than one of those methods is called, an exception will
* be thrown.
*
- * @see MediaBrowserService#onLoadChildren
- * @see MediaBrowserService#onLoadItem
+ * @see #onLoadChildren
+ * @see #onLoadItem
*/
public class Result<T> {
private Object mDebug;
@@ -367,10 +368,16 @@
* {@link Result#detach result.detach} may be called before returning from
* this function, and then {@link Result#sendResult result.sendResult}
* called when the loading is complete.
+ * </p><p>
+ * In case the media item does not have any children, call {@link Result#sendResult}
+ * with an empty list which is not {@code null}. If {@code null} is sent that means
+ * the given {@code parentId} is invalid and {@link MediaBrowser.SubscriptionCallback#onError}
+ * will be called.
+ * </p>
*
* @param parentId The id of the parent media item whose children are to be
* queried.
- * @param result The Result to send the list of children to, or null if the
+ * @param result The Result to send the list of children to. Send null if the
* id is invalid.
*/
public abstract void onLoadChildren(@NonNull String parentId,
@@ -385,10 +392,16 @@
* {@link Result#detach result.detach} may be called before returning from
* this function, and then {@link Result#sendResult result.sendResult}
* called when the loading is complete.
+ * </p><p>
+ * In case the media item does not have any children, call {@link Result#sendResult}
+ * with an empty list which is not {@code null}. If {@code null} is sent that means
+ * the given {@code parentId} is invalid and {@link MediaBrowser.SubscriptionCallback#onError}
+ * will be called.
+ * </p>
*
* @param parentId The id of the parent media item whose children are to be
* queried.
- * @param result The Result to send the list of children to, or null if the
+ * @param result The Result to send the list of children to. Send null if the
* id is invalid.
* @param options A bundle of service-specific arguments sent from the media
* browse. The information returned through the result should be
@@ -416,7 +429,7 @@
*
* @param itemId The id for the specific
* {@link android.media.browse.MediaBrowser.MediaItem}.
- * @param result The Result to send the item to, or null if the id is
+ * @param result The Result to send the item to. Send null if the id is
* invalid.
*/
public void onLoadItem(String itemId, Result<MediaBrowser.MediaItem> result) {
@@ -630,6 +643,9 @@
private List<MediaBrowser.MediaItem> applyOptions(List<MediaBrowser.MediaItem> list,
final Bundle options) {
+ if (list == null) {
+ return null;
+ }
int page = options.getInt(MediaBrowser.EXTRA_PAGE, -1);
int pageSize = options.getInt(MediaBrowser.EXTRA_PAGE_SIZE, -1);
if (page == -1 && pageSize == -1) {
@@ -638,7 +654,7 @@
int fromIndex = pageSize * (page - 1);
int toIndex = fromIndex + pageSize;
if (page < 1 || pageSize < 1 || fromIndex >= list.size()) {
- return null;
+ return Collections.EMPTY_LIST;
}
if (toIndex > list.size()) {
toIndex = list.size();
diff --git a/media/jni/Android.mk b/media/jni/Android.mk
index fa9c48c..29739ca 100644
--- a/media/jni/Android.mk
+++ b/media/jni/Android.mk
@@ -64,7 +64,6 @@
frameworks/av/media/mtp \
frameworks/native/include/media/openmax \
$(call include-path-for, libhardware)/hardware \
- system/media/camera/include \
$(PV_INCLUDES) \
$(JNI_H_INCLUDE)
diff --git a/media/jni/android_media_MediaDataSource.cpp b/media/jni/android_media_MediaDataSource.cpp
index 3b892cb..537b56d 100644
--- a/media/jni/android_media_MediaDataSource.cpp
+++ b/media/jni/android_media_MediaDataSource.cpp
@@ -116,7 +116,8 @@
return UNKNOWN_ERROR;
}
if (mSizeIsCached) {
- return mCachedSize;
+ *size = mCachedSize;
+ return OK;
}
JNIEnv* env = AndroidRuntime::getJNIEnv();
diff --git a/media/jni/android_media_MediaRecorder.cpp b/media/jni/android_media_MediaRecorder.cpp
index 701f7ac..922ad79 100644
--- a/media/jni/android_media_MediaRecorder.cpp
+++ b/media/jni/android_media_MediaRecorder.cpp
@@ -26,7 +26,6 @@
#include <utils/Log.h>
#include <gui/Surface.h>
-#include <camera/ICameraService.h>
#include <camera/Camera.h>
#include <media/mediarecorder.h>
#include <media/stagefright/PersistentSurface.h>
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkUnitTestRunner.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkUnitTestRunner.java
index 61dede3..9be7004 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkUnitTestRunner.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkUnitTestRunner.java
@@ -60,10 +60,7 @@
}
private void addCameraUnitTests(TestSuite suite) {
- suite.addTestSuite(CameraUtilsDecoratorTest.class);
- suite.addTestSuite(CameraUtilsRuntimeExceptionTest.class);
suite.addTestSuite(CameraUtilsUncheckedThrowTest.class);
- suite.addTestSuite(CameraUtilsBinderDecoratorTest.class);
suite.addTestSuite(CameraUtilsTypeReferenceTest.class);
suite.addTestSuite(CameraMetadataTest.class);
}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTest.java
index 6f74203..9a0946e 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTest.java
@@ -19,16 +19,16 @@
import android.hardware.CameraInfo;
import android.hardware.ICamera;
import android.hardware.ICameraClient;
+import android.hardware.ICameraService;
import android.hardware.ICameraServiceListener;
import android.hardware.camera2.ICameraDeviceCallbacks;
import android.hardware.camera2.ICameraDeviceUser;
import android.hardware.camera2.impl.CameraMetadataNative;
import android.hardware.camera2.impl.CaptureResultExtras;
-import android.hardware.camera2.utils.BinderHolder;
-import android.hardware.camera2.utils.CameraBinderDecorator;
import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
+import android.os.ServiceSpecificException;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.SmallTest;
import android.util.Log;
@@ -84,14 +84,7 @@
public void testCameraInfo() throws Exception {
for (int cameraId = 0; cameraId < mUtils.getGuessedNumCameras(); ++cameraId) {
- CameraInfo info = new CameraInfo();
- info.info.facing = -1;
- info.info.orientation = -1;
-
- assertTrue(
- "Camera service returned info for camera " + cameraId,
- mUtils.getCameraService().getCameraInfo(cameraId, info) ==
- CameraBinderTestUtils.NO_ERROR);
+ CameraInfo info = mUtils.getCameraService().getCameraInfo(cameraId);
assertTrue("Facing was not set for camera " + cameraId, info.info.facing != -1);
assertTrue("Orientation was not set for camera " + cameraId,
info.info.orientation != -1);
@@ -105,20 +98,17 @@
public void testGetLegacyParameters() throws Exception {
for (int cameraId = 0; cameraId < mUtils.getGuessedNumCameras(); ++cameraId) {
- String[] parameters = new String[1];
- assertEquals("Camera service returned parameters for camera " + cameraId,
- CameraBinderTestUtils.NO_ERROR,
- mUtils.getCameraService().getLegacyParameters(cameraId, /*out*/parameters));
- assertNotNull(parameters[0]);
+ String parameters = mUtils.getCameraService().getLegacyParameters(cameraId);
+ assertNotNull(parameters);
assertTrue("Parameters should have at least one character in it",
- parameters[0].length() > 0);
+ parameters.length() > 0);
- int end = parameters[0].length();
+ int end = parameters.length();
if (end > MAX_PARAMETERS_LENGTH) {
end = MAX_PARAMETERS_LENGTH;
}
- Log.v(TAG, "Camera " + cameraId + " parameters: " + parameters[0].substring(0, end));
+ Log.v(TAG, "Camera " + cameraId + " parameters: " + parameters.substring(0, end));
}
}
@@ -127,14 +117,8 @@
public void testSupportsCamera2Api() throws Exception {
for (int cameraId = 0; cameraId < mUtils.getGuessedNumCameras(); ++cameraId) {
- int res = mUtils.getCameraService().supportsCameraApi(cameraId, API_VERSION_2);
+ boolean supports = mUtils.getCameraService().supportsCameraApi(cameraId, API_VERSION_2);
- if (res != CameraBinderTestUtils.NO_ERROR && res != -android.system.OsConstants.EOPNOTSUPP) {
- fail("Camera service returned bad value when queried if it supports camera2 api: "
- + res + " for camera ID " + cameraId);
- }
-
- boolean supports = res == CameraBinderTestUtils.NO_ERROR;
Log.v(TAG, "Camera " + cameraId + " supports api2: " + supports);
}
}
@@ -144,10 +128,10 @@
public void testSupportsCamera1Api() throws Exception {
for (int cameraId = 0; cameraId < mUtils.getGuessedNumCameras(); ++cameraId) {
- int res = mUtils.getCameraService().supportsCameraApi(cameraId, API_VERSION_1);
- assertEquals(
- "Camera service returned bad value when queried if it supports camera1 api: "
- + res + " for camera ID " + cameraId, CameraBinderTestUtils.NO_ERROR, res);
+ boolean supports = mUtils.getCameraService().supportsCameraApi(cameraId, API_VERSION_1);
+ assertTrue(
+ "Camera service returned false when queried if it supports camera1 api " +
+ " for camera ID " + cameraId, supports);
}
}
@@ -169,11 +153,10 @@
String clientPackageName = getContext().getPackageName();
- BinderHolder holder = new BinderHolder();
- CameraBinderDecorator.newInstance(mUtils.getCameraService())
+ ICamera cameraUser = mUtils.getCameraService()
.connect(dummyCallbacks, cameraId, clientPackageName,
- CameraBinderTestUtils.USE_CALLING_UID, holder);
- ICamera cameraUser = ICamera.Stub.asInterface(holder.getBinder());
+ ICameraService.USE_CALLING_UID,
+ ICameraService.USE_CALLING_PID);
assertNotNull(String.format("Camera %s was null", cameraId), cameraUser);
Log.v(TAG, String.format("Camera %s connected", cameraId));
@@ -191,14 +174,11 @@
String clientPackageName = getContext().getPackageName();
- BinderHolder holder = new BinderHolder();
-
try {
- CameraBinderDecorator.newInstance(mUtils.getCameraService())
+ cameraUser = mUtils.getCameraService()
.connectLegacy(dummyCallbacks, cameraId, CAMERA_HAL_API_VERSION_1_0,
- clientPackageName,
- CameraBinderTestUtils.USE_CALLING_UID, holder);
- cameraUser = ICamera.Stub.asInterface(holder.getBinder());
+ clientPackageName,
+ ICameraService.USE_CALLING_UID);
assertNotNull(String.format("Camera %s was null", cameraId), cameraUser);
Log.v(TAG, String.format("Camera %s connected as HAL1 legacy device", cameraId));
@@ -284,11 +264,11 @@
String clientPackageName = getContext().getPackageName();
- BinderHolder holder = new BinderHolder();
- CameraBinderDecorator.newInstance(mUtils.getCameraService())
- .connectDevice(dummyCallbacks, cameraId,
- clientPackageName, CameraBinderTestUtils.USE_CALLING_UID, holder);
- ICameraDeviceUser cameraUser = ICameraDeviceUser.Stub.asInterface(holder.getBinder());
+ ICameraDeviceUser cameraUser =
+ mUtils.getCameraService().connectDevice(
+ dummyCallbacks, cameraId,
+ clientPackageName,
+ ICameraService.USE_CALLING_UID);
assertNotNull(String.format("Camera %s was null", cameraId), cameraUser);
Log.v(TAG, String.format("Camera %s connected", cameraId));
@@ -323,27 +303,33 @@
ICameraServiceListener listener = new DummyCameraServiceListener();
- assertTrue(
- "Listener was removed before added",
- mUtils.getCameraService().removeListener(listener) ==
- CameraBinderTestUtils.BAD_VALUE);
+ try {
+ mUtils.getCameraService().removeListener(listener);
+ fail("Listener was removed before added");
+ } catch (ServiceSpecificException e) {
+ assertEquals("Listener was removed before added",
+ e.errorCode, ICameraService.ERROR_ILLEGAL_ARGUMENT);
+ }
- assertTrue("Listener was not added",
- mUtils.getCameraService().addListener(listener) ==
- CameraBinderTestUtils.NO_ERROR);
- assertTrue(
- "Listener was wrongly added again",
- mUtils.getCameraService().addListener(listener) ==
- CameraBinderTestUtils.ALREADY_EXISTS);
+ mUtils.getCameraService().addListener(listener);
- assertTrue(
- "Listener was not removed",
- mUtils.getCameraService().removeListener(listener) ==
- CameraBinderTestUtils.NO_ERROR);
- assertTrue(
- "Listener was wrongly removed again",
- mUtils.getCameraService().removeListener(listener) ==
- CameraBinderTestUtils.BAD_VALUE);
+ try {
+ mUtils.getCameraService().addListener(listener);
+ fail("Listener was wrongly added again");
+ } catch (ServiceSpecificException e) {
+ assertEquals("Listener was wrongly added again",
+ e.errorCode, ICameraService.ERROR_ALREADY_EXISTS);
+ }
+
+ mUtils.getCameraService().removeListener(listener);
+
+ try {
+ mUtils.getCameraService().removeListener(listener);
+ fail("Listener was wrongly removed twice");
+ } catch (ServiceSpecificException e) {
+ assertEquals("Listener was wrongly removed twice",
+ e.errorCode, ICameraService.ERROR_ILLEGAL_ARGUMENT);
+ }
}
}
}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTestUtils.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTestUtils.java
index 5c4b23b..38fc49f 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTestUtils.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTestUtils.java
@@ -18,10 +18,6 @@
static final String CAMERA_SERVICE_BINDER_NAME = "media.camera";
- protected static final int USE_CALLING_UID = -1;
- protected static final int BAD_VALUE = -EINVAL;
- protected static final int INVALID_OPERATION = -ENOSYS;
- protected static final int ALREADY_EXISTS = -EEXIST;
public static final int NO_ERROR = 0;
private final Context mContext;
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraDeviceBinderTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraDeviceBinderTest.java
index d71b44b..5c1d8a7 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraDeviceBinderTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraDeviceBinderTest.java
@@ -18,6 +18,7 @@
import android.graphics.ImageFormat;
import android.graphics.SurfaceTexture;
+import android.hardware.ICameraService;
import android.hardware.camera2.CameraMetadata;
import android.hardware.camera2.CameraCaptureSession;
import android.hardware.camera2.CameraCharacteristics;
@@ -27,12 +28,13 @@
import android.hardware.camera2.impl.CameraMetadataNative;
import android.hardware.camera2.impl.CaptureResultExtras;
import android.hardware.camera2.params.OutputConfiguration;
-import android.hardware.camera2.utils.BinderHolder;
+import android.hardware.camera2.utils.SubmitInfo;
import android.media.Image;
import android.media.ImageReader;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.RemoteException;
+import android.os.ServiceSpecificException;
import android.os.SystemClock;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.SmallTest;
@@ -164,11 +166,10 @@
}
private CaptureRequest.Builder createDefaultBuilder(boolean needStream) throws Exception {
- CameraMetadataNative metadata = new CameraMetadataNative();
+ CameraMetadataNative metadata = null;
assertTrue(metadata.isEmpty());
- int status = mCameraUser.createDefaultRequest(TEMPLATE_PREVIEW, /* out */metadata);
- assertEquals(CameraBinderTestUtils.NO_ERROR, status);
+ metadata = mCameraUser.createDefaultRequest(TEMPLATE_PREVIEW);
assertFalse(metadata.isEmpty());
CaptureRequest.Builder request = new CaptureRequest.Builder(metadata, /*reprocess*/false,
@@ -183,12 +184,13 @@
return request;
}
- private int submitCameraRequest(CaptureRequest request, boolean streaming) throws Exception {
- int requestId = mCameraUser.submitRequest(request, streaming, null);
+ private SubmitInfo submitCameraRequest(CaptureRequest request, boolean streaming) throws Exception {
+ SubmitInfo requestInfo = mCameraUser.submitRequest(request, streaming);
assertTrue(
- "Request IDs should be non-negative (expected: >= 0, actual: " + requestId + ")",
- requestId >= 0);
- return requestId;
+ "Request IDs should be non-negative (expected: >= 0, actual: " +
+ requestInfo.getRequestId() + ")",
+ requestInfo.getRequestId() >= 0);
+ return requestInfo;
}
@Override
@@ -214,10 +216,8 @@
mMockCb = spy(dummyCallbacks);
- BinderHolder holder = new BinderHolder();
- mUtils.getCameraService().connectDevice(mMockCb, mCameraId,
- clientPackageName, CameraBinderTestUtils.USE_CALLING_UID, holder);
- mCameraUser = ICameraDeviceUser.Stub.asInterface(holder.getBinder());
+ mCameraUser = mUtils.getCameraService().connectDevice(mMockCb, mCameraId,
+ clientPackageName, ICameraService.USE_CALLING_UID);
assertNotNull(String.format("Camera %s was null", mCameraId), mCameraUser);
mHandlerThread = new HandlerThread(TAG);
mHandlerThread.start();
@@ -238,11 +238,10 @@
@SmallTest
public void testCreateDefaultRequest() throws Exception {
- CameraMetadataNative metadata = new CameraMetadataNative();
+ CameraMetadataNative metadata = null;
assertTrue(metadata.isEmpty());
- int status = mCameraUser.createDefaultRequest(TEMPLATE_PREVIEW, /* out */metadata);
- assertEquals(CameraBinderTestUtils.NO_ERROR, status);
+ metadata = mCameraUser.createDefaultRequest(TEMPLATE_PREVIEW);
assertFalse(metadata.isEmpty());
}
@@ -252,18 +251,28 @@
int streamId = mCameraUser.createStream(mOutputConfiguration);
assertEquals(0, streamId);
- assertEquals(CameraBinderTestUtils.ALREADY_EXISTS,
- mCameraUser.createStream(mOutputConfiguration));
+ try {
+ mCameraUser.createStream(mOutputConfiguration);
+ fail("Creating same stream twice");
+ } catch (ServiceSpecificException e) {
+ assertEquals("Creating same stream twice",
+ e.errorCode, ICameraService.ERROR_ALREADY_EXISTS);
+ }
- assertEquals(CameraBinderTestUtils.NO_ERROR, mCameraUser.deleteStream(streamId));
+ mCameraUser.deleteStream(streamId);
}
@SmallTest
public void testDeleteInvalidStream() throws Exception {
- assertEquals(CameraBinderTestUtils.BAD_VALUE, mCameraUser.deleteStream(-1));
- assertEquals(CameraBinderTestUtils.BAD_VALUE, mCameraUser.deleteStream(0));
- assertEquals(CameraBinderTestUtils.BAD_VALUE, mCameraUser.deleteStream(1));
- assertEquals(CameraBinderTestUtils.BAD_VALUE, mCameraUser.deleteStream(0xC0FFEE));
+ int[] badStreams = { -1, 0, 1, 0xC0FFEE };
+ for (int badStream : badStreams) {
+ try {
+ mCameraUser.deleteStream(badStream);
+ fail("Allowed bad stream delete");
+ } catch (ServiceSpecificException e) {
+ assertEquals(e.errorCode, ICameraService.ERROR_ILLEGAL_ARGUMENT);
+ }
+ }
}
@SmallTest
@@ -273,8 +282,13 @@
int streamId = mCameraUser.createStream(mOutputConfiguration);
assertEquals(0, streamId);
- assertEquals(CameraBinderTestUtils.ALREADY_EXISTS,
- mCameraUser.createStream(mOutputConfiguration));
+ try {
+ mCameraUser.createStream(mOutputConfiguration);
+ fail("Created same stream twice");
+ } catch (ServiceSpecificException e) {
+ assertEquals("Created same stream twice",
+ ICameraService.ERROR_ALREADY_EXISTS, e.errorCode);
+ }
// Create second stream with a different surface.
SurfaceTexture surfaceTexture = new SurfaceTexture(/* ignored */0);
@@ -286,8 +300,8 @@
assertEquals(1, streamId2);
// Clean up streams
- assertEquals(CameraBinderTestUtils.NO_ERROR, mCameraUser.deleteStream(streamId));
- assertEquals(CameraBinderTestUtils.NO_ERROR, mCameraUser.deleteStream(streamId2));
+ mCameraUser.deleteStream(streamId);
+ mCameraUser.deleteStream(streamId2);
}
@SmallTest
@@ -295,16 +309,25 @@
CaptureRequest.Builder builder = createDefaultBuilder(/* needStream */false);
CaptureRequest request1 = builder.build();
- int status = mCameraUser.submitRequest(request1, /* streaming */false, null);
- assertEquals("Expected submitRequest to return BAD_VALUE " +
- "since we had 0 surface targets set.", CameraBinderTestUtils.BAD_VALUE, status);
+ try {
+ SubmitInfo requestInfo = mCameraUser.submitRequest(request1, /* streaming */false);
+ fail("Exception expected");
+ } catch(ServiceSpecificException e) {
+ assertEquals("Expected submitRequest to throw ServiceSpecificException with BAD_VALUE " +
+ "since we had 0 surface targets set.", ICameraService.ERROR_ILLEGAL_ARGUMENT,
+ e.errorCode);
+ }
builder.addTarget(mSurface);
CaptureRequest request2 = builder.build();
- status = mCameraUser.submitRequest(request2, /* streaming */false, null);
- assertEquals("Expected submitRequest to return BAD_VALUE since " +
- "the target surface wasn't registered with createStream.",
- CameraBinderTestUtils.BAD_VALUE, status);
+ try {
+ SubmitInfo requestInfo = mCameraUser.submitRequest(request2, /* streaming */false);
+ fail("Exception expected");
+ } catch(ServiceSpecificException e) {
+ assertEquals("Expected submitRequest to throw ILLEGAL_ARGUMENT " +
+ "ServiceSpecificException since the target wasn't registered with createStream.",
+ ICameraService.ERROR_ILLEGAL_ARGUMENT, e.errorCode);
+ }
}
@SmallTest
@@ -314,9 +337,10 @@
CaptureRequest request = builder.build();
// Submit valid request twice.
- int requestId1 = submitCameraRequest(request, /* streaming */false);
- int requestId2 = submitCameraRequest(request, /* streaming */false);
- assertNotSame("Request IDs should be unique for multiple requests", requestId1, requestId2);
+ SubmitInfo requestInfo1 = submitCameraRequest(request, /* streaming */false);
+ SubmitInfo requestInfo2 = submitCameraRequest(request, /* streaming */false);
+ assertNotSame("Request IDs should be unique for multiple requests",
+ requestInfo1.getRequestId(), requestInfo2.getRequestId());
}
@@ -329,32 +353,35 @@
// Submit valid request once (non-streaming), and another time
// (streaming)
- int requestId1 = submitCameraRequest(request, /* streaming */false);
+ SubmitInfo requestInfo1 = submitCameraRequest(request, /* streaming */false);
- int requestIdStreaming = submitCameraRequest(request, /* streaming */true);
- assertNotSame("Request IDs should be unique for multiple requests", requestId1,
- requestIdStreaming);
+ SubmitInfo requestInfoStreaming = submitCameraRequest(request, /* streaming */true);
+ assertNotSame("Request IDs should be unique for multiple requests",
+ requestInfo1.getRequestId(),
+ requestInfoStreaming.getRequestId());
- int status = mCameraUser.cancelRequest(-1, null);
- assertEquals("Invalid request IDs should not be cancellable",
- CameraBinderTestUtils.BAD_VALUE, status);
+ try {
+ long lastFrameNumber = mCameraUser.cancelRequest(-1);
+ fail("Expected exception");
+ } catch (ServiceSpecificException e) {
+ assertEquals("Invalid request IDs should not be cancellable",
+ ICameraService.ERROR_ILLEGAL_ARGUMENT, e.errorCode);
+ }
- status = mCameraUser.cancelRequest(requestId1, null);
- assertEquals("Non-streaming request IDs should not be cancellable",
- CameraBinderTestUtils.BAD_VALUE, status);
+ try {
+ long lastFrameNumber = mCameraUser.cancelRequest(requestInfo1.getRequestId());
+ fail("Expected exception");
+ } catch (ServiceSpecificException e) {
+ assertEquals("Non-streaming request IDs should not be cancellable",
+ ICameraService.ERROR_ILLEGAL_ARGUMENT, e.errorCode);
+ }
- status = mCameraUser.cancelRequest(requestIdStreaming, null);
- assertEquals("Streaming request IDs should be cancellable", CameraBinderTestUtils.NO_ERROR,
- status);
-
+ long lastFrameNumber = mCameraUser.cancelRequest(requestInfoStreaming.getRequestId());
}
@SmallTest
public void testCameraInfo() throws RemoteException {
- CameraMetadataNative info = new CameraMetadataNative();
-
- int status = mCameraUser.getCameraInfo(/*out*/info);
- assertEquals(CameraBinderTestUtils.NO_ERROR, status);
+ CameraMetadataNative info = mCameraUser.getCameraInfo();
assertFalse(info.isEmpty());
assertNotNull(info.get(CameraCharacteristics.SCALER_AVAILABLE_FORMATS));
@@ -362,10 +389,7 @@
@SmallTest
public void testCameraCharacteristics() throws RemoteException {
- CameraMetadataNative info = new CameraMetadataNative();
-
- int status = mUtils.getCameraService().getCameraCharacteristics(mCameraId, /*out*/info);
- assertEquals(CameraBinderTestUtils.NO_ERROR, status);
+ CameraMetadataNative info = mUtils.getCameraService().getCameraCharacteristics(mCameraId);
assertFalse(info.isEmpty());
assertNotNull(info.get(CameraCharacteristics.SCALER_AVAILABLE_FORMATS));
@@ -374,18 +398,19 @@
@SmallTest
public void testWaitUntilIdle() throws Exception {
CaptureRequest.Builder builder = createDefaultBuilder(/* needStream */true);
- int requestIdStreaming = submitCameraRequest(builder.build(), /* streaming */true);
+ SubmitInfo requestInfoStreaming = submitCameraRequest(builder.build(), /* streaming */true);
// Test Bad case first: waitUntilIdle when there is active repeating request
- int status = mCameraUser.waitUntilIdle();
- assertEquals("waitUntilIdle is invalid operation when there is active repeating request",
- CameraBinderTestUtils.INVALID_OPERATION, status);
+ try {
+ mCameraUser.waitUntilIdle();
+ } catch (ServiceSpecificException e) {
+ assertEquals("waitUntilIdle is invalid operation when there is active repeating request",
+ ICameraService.ERROR_INVALID_OPERATION, e.errorCode);
+ }
// Test good case, waitUntilIdle when there is no active repeating request
- status = mCameraUser.cancelRequest(requestIdStreaming, null);
- assertEquals(CameraBinderTestUtils.NO_ERROR, status);
- status = mCameraUser.waitUntilIdle();
- assertEquals(CameraBinderTestUtils.NO_ERROR, status);
+ long lastFrameNumber = mCameraUser.cancelRequest(requestInfoStreaming.getRequestId());
+ mCameraUser.waitUntilIdle();
}
@SmallTest
@@ -411,12 +436,12 @@
ArgumentCaptor<Long> timestamps = ArgumentCaptor.forClass(Long.class);
// Test both single request and streaming request.
- int requestId1 = submitCameraRequest(request, /* streaming */false);
+ SubmitInfo requestInfo1 = submitCameraRequest(request, /* streaming */false);
verify(mMockCb, timeout(WAIT_FOR_COMPLETE_TIMEOUT_MS).times(1)).onCaptureStarted(
any(CaptureResultExtras.class),
anyLong());
- int streamingId = submitCameraRequest(request, /* streaming */true);
+ SubmitInfo streamingInfo = submitCameraRequest(request, /* streaming */true);
verify(mMockCb, timeout(WAIT_FOR_COMPLETE_TIMEOUT_MS).atLeast(NUM_CALLBACKS_CHECKED))
.onCaptureStarted(
any(CaptureResultExtras.class),
@@ -436,22 +461,22 @@
CaptureRequest request = createDefaultBuilder(/* needStream */true).build();
// Try streaming
- int streamingId = submitCameraRequest(request, /* streaming */true);
+ SubmitInfo streamingInfo = submitCameraRequest(request, /* streaming */true);
// Wait a bit to fill up the queue
SystemClock.sleep(WAIT_FOR_WORK_MS);
// Cancel and make sure we eventually quiesce
- status = mCameraUser.cancelRequest(streamingId, null);
+ long lastFrameNumber = mCameraUser.cancelRequest(streamingInfo.getRequestId());
verify(mMockCb, timeout(WAIT_FOR_IDLE_TIMEOUT_MS).times(1)).onDeviceIdle();
// Submit a few capture requests
- int requestId1 = submitCameraRequest(request, /* streaming */false);
- int requestId2 = submitCameraRequest(request, /* streaming */false);
- int requestId3 = submitCameraRequest(request, /* streaming */false);
- int requestId4 = submitCameraRequest(request, /* streaming */false);
- int requestId5 = submitCameraRequest(request, /* streaming */false);
+ SubmitInfo requestInfo1 = submitCameraRequest(request, /* streaming */false);
+ SubmitInfo requestInfo2 = submitCameraRequest(request, /* streaming */false);
+ SubmitInfo requestInfo3 = submitCameraRequest(request, /* streaming */false);
+ SubmitInfo requestInfo4 = submitCameraRequest(request, /* streaming */false);
+ SubmitInfo requestInfo5 = submitCameraRequest(request, /* streaming */false);
// And wait for more idle
verify(mMockCb, timeout(WAIT_FOR_IDLE_TIMEOUT_MS).times(2)).onDeviceIdle();
@@ -463,38 +488,34 @@
int status;
// Initial flush should work
- status = mCameraUser.flush(null);
- assertEquals(CameraBinderTestUtils.NO_ERROR, status);
+ long lastFrameNumber = mCameraUser.flush();
// Then set up a stream
CaptureRequest request = createDefaultBuilder(/* needStream */true).build();
// Flush should still be a no-op, really
- status = mCameraUser.flush(null);
- assertEquals(CameraBinderTestUtils.NO_ERROR, status);
+ lastFrameNumber = mCameraUser.flush();
// Submit a few capture requests
- int requestId1 = submitCameraRequest(request, /* streaming */false);
- int requestId2 = submitCameraRequest(request, /* streaming */false);
- int requestId3 = submitCameraRequest(request, /* streaming */false);
- int requestId4 = submitCameraRequest(request, /* streaming */false);
- int requestId5 = submitCameraRequest(request, /* streaming */false);
+ SubmitInfo requestInfo1 = submitCameraRequest(request, /* streaming */false);
+ SubmitInfo requestInfo2 = submitCameraRequest(request, /* streaming */false);
+ SubmitInfo requestInfo3 = submitCameraRequest(request, /* streaming */false);
+ SubmitInfo requestInfo4 = submitCameraRequest(request, /* streaming */false);
+ SubmitInfo requestInfo5 = submitCameraRequest(request, /* streaming */false);
// Then flush and wait for idle
- status = mCameraUser.flush(null);
- assertEquals(CameraBinderTestUtils.NO_ERROR, status);
+ lastFrameNumber = mCameraUser.flush();
verify(mMockCb, timeout(WAIT_FOR_FLUSH_TIMEOUT_MS).times(1)).onDeviceIdle();
// Now a streaming request
- int streamingId = submitCameraRequest(request, /* streaming */true);
+ SubmitInfo streamingInfo = submitCameraRequest(request, /* streaming */true);
// Wait a bit to fill up the queue
SystemClock.sleep(WAIT_FOR_WORK_MS);
// Then flush and wait for the idle callback
- status = mCameraUser.flush(null);
- assertEquals(CameraBinderTestUtils.NO_ERROR, status);
+ lastFrameNumber = mCameraUser.flush();
verify(mMockCb, timeout(WAIT_FOR_FLUSH_TIMEOUT_MS).times(2)).onDeviceIdle();
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraUtilsBinderDecoratorTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraUtilsBinderDecoratorTest.java
deleted file mode 100644
index 33c6388..0000000
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraUtilsBinderDecoratorTest.java
+++ /dev/null
@@ -1,173 +0,0 @@
-/*
- * Copyright (C) 2013 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.mediaframeworktest.unit;
-
-import android.hardware.camera2.CameraAccessException;
-import android.hardware.camera2.utils.CameraBinderDecorator;
-import android.hardware.camera2.utils.CameraRuntimeException;
-import android.os.DeadObjectException;
-import android.os.RemoteException;
-import android.os.TransactionTooLargeException;
-import android.test.suitebuilder.annotation.SmallTest;
-
-import static org.mockito.Mockito.*;
-import static android.hardware.camera2.utils.CameraBinderDecorator.*;
-import static android.hardware.camera2.CameraAccessException.*;
-import static android.system.OsConstants.*;
-
-import junit.framework.Assert;
-
-public class CameraUtilsBinderDecoratorTest extends junit.framework.TestCase {
-
- private interface ICameraBinderStereotype {
-
- double doNothing();
-
- // int is a 'status_t'
- int doSomethingPositive();
-
- int doSomethingNoError();
-
- int doSomethingPermissionDenied();
-
- int doSomethingAlreadyExists();
-
- int doSomethingBadValue();
-
- int doSomethingDeadObject() throws CameraRuntimeException;
-
- int doSomethingBadPolicy() throws CameraRuntimeException;
-
- int doSomethingDeviceBusy() throws CameraRuntimeException;
-
- int doSomethingNoSuchDevice() throws CameraRuntimeException;
-
- int doSomethingUnknownErrorCode();
-
- int doSomethingThrowDeadObjectException() throws RemoteException;
-
- int doSomethingThrowTransactionTooLargeException() throws RemoteException;
- }
-
- private static final double SOME_ARBITRARY_DOUBLE = 1.0;
- private static final int SOME_ARBITRARY_POSITIVE_INT = 5;
- private static final int SOME_ARBITRARY_NEGATIVE_INT = -0xC0FFEE;
-
- @SmallTest
- public void testStereotypes() {
-
- ICameraBinderStereotype mock = mock(ICameraBinderStereotype.class);
- try {
- when(mock.doNothing()).thenReturn(SOME_ARBITRARY_DOUBLE);
- when(mock.doSomethingPositive()).thenReturn(SOME_ARBITRARY_POSITIVE_INT);
- when(mock.doSomethingNoError()).thenReturn(NO_ERROR);
- when(mock.doSomethingPermissionDenied()).thenReturn(PERMISSION_DENIED);
- when(mock.doSomethingAlreadyExists()).thenReturn(ALREADY_EXISTS);
- when(mock.doSomethingBadValue()).thenReturn(BAD_VALUE);
- when(mock.doSomethingDeadObject()).thenReturn(DEAD_OBJECT);
- when(mock.doSomethingBadPolicy()).thenReturn(-EACCES);
- when(mock.doSomethingDeviceBusy()).thenReturn(-EBUSY);
- when(mock.doSomethingNoSuchDevice()).thenReturn(-ENODEV);
- when(mock.doSomethingUnknownErrorCode()).thenReturn(SOME_ARBITRARY_NEGATIVE_INT);
- when(mock.doSomethingThrowDeadObjectException()).thenThrow(new DeadObjectException());
- when(mock.doSomethingThrowTransactionTooLargeException()).thenThrow(
- new TransactionTooLargeException());
- } catch (RemoteException e) {
- Assert.fail("Unreachable");
- }
-
- ICameraBinderStereotype decoratedMock = CameraBinderDecorator.newInstance(mock);
-
- // ignored by decorator because return type is double, not int
- assertEquals(SOME_ARBITRARY_DOUBLE, decoratedMock.doNothing());
-
- // pass through for positive values
- assertEquals(SOME_ARBITRARY_POSITIVE_INT, decoratedMock.doSomethingPositive());
-
- // pass through NO_ERROR
- assertEquals(NO_ERROR, decoratedMock.doSomethingNoError());
-
- try {
- decoratedMock.doSomethingPermissionDenied();
- Assert.fail("Should've thrown SecurityException");
- } catch (SecurityException e) {
- }
-
- assertEquals(ALREADY_EXISTS, decoratedMock.doSomethingAlreadyExists());
-
- try {
- decoratedMock.doSomethingBadValue();
- Assert.fail("Should've thrown IllegalArgumentException");
- } catch (IllegalArgumentException e) {
- }
-
- try {
- decoratedMock.doSomethingDeadObject();
- Assert.fail("Should've thrown CameraRuntimeException");
- } catch (CameraRuntimeException e) {
- assertEquals(CAMERA_DISCONNECTED, e.getReason());
- }
-
- try {
- decoratedMock.doSomethingBadPolicy();
- Assert.fail("Should've thrown CameraRuntimeException");
- } catch (CameraRuntimeException e) {
- assertEquals(CAMERA_DISABLED, e.getReason());
- }
-
- try {
- decoratedMock.doSomethingDeviceBusy();
- Assert.fail("Should've thrown CameraRuntimeException");
- } catch (CameraRuntimeException e) {
- assertEquals(CAMERA_IN_USE, e.getReason());
- }
-
- try {
- decoratedMock.doSomethingNoSuchDevice();
- Assert.fail("Should've thrown CameraRuntimeException");
- } catch (CameraRuntimeException e) {
- assertEquals(CAMERA_DISCONNECTED, e.getReason());
- }
-
- try {
- decoratedMock.doSomethingUnknownErrorCode();
- Assert.fail("Should've thrown UnsupportedOperationException");
- } catch (UnsupportedOperationException e) {
- assertEquals(String.format("Unknown error %d",
- SOME_ARBITRARY_NEGATIVE_INT), e.getMessage());
- }
-
- try {
- decoratedMock.doSomethingThrowDeadObjectException();
- Assert.fail("Should've thrown CameraRuntimeException");
- } catch (CameraRuntimeException e) {
- assertEquals(CAMERA_DISCONNECTED, e.getReason());
- } catch (RemoteException e) {
- Assert.fail("Should not throw a DeadObjectException directly, but rethrow");
- }
-
- try {
- decoratedMock.doSomethingThrowTransactionTooLargeException();
- Assert.fail("Should've thrown UnsupportedOperationException");
- } catch (UnsupportedOperationException e) {
- assertTrue(e.getCause() instanceof TransactionTooLargeException);
- } catch (RemoteException e) {
- Assert.fail("Should not throw a TransactionTooLargeException directly, but rethrow");
- }
- }
-
-}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraUtilsDecoratorTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraUtilsDecoratorTest.java
deleted file mode 100644
index c3b6006..0000000
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraUtilsDecoratorTest.java
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * Copyright (C) 2013 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.mediaframeworktest.unit;
-
-import android.test.suitebuilder.annotation.SmallTest;
-import android.hardware.camera2.utils.*;
-import android.hardware.camera2.utils.Decorator.DecoratorListener;
-
-import junit.framework.Assert;
-
-import java.lang.reflect.Method;
-
-/**
- * adb shell am instrument -e class 'com.android.mediaframeworktest.unit.CameraUtilsDecoratorTest' \
- * -w com.android.mediaframeworktest/.MediaFrameworkUnitTestRunner
- */
-public class CameraUtilsDecoratorTest extends junit.framework.TestCase {
- private DummyListener mDummyListener;
- private DummyInterface mIface;
-
- @Override
- public void setUp() {
- mDummyListener = new DummyListener();
- mIface = Decorator.newInstance(new DummyImpl(), mDummyListener);
- }
-
- interface DummyInterface {
- int addValues(int x, int y, int z);
-
- void raiseException() throws Exception;
-
- void raiseUnsupportedOperationException() throws UnsupportedOperationException;
- }
-
- class DummyImpl implements DummyInterface {
- @Override
- public int addValues(int x, int y, int z) {
- return x + y + z;
- }
-
- @Override
- public void raiseException() throws Exception {
- throw new Exception("Test exception");
- }
-
- @Override
- public void raiseUnsupportedOperationException() throws UnsupportedOperationException {
- throw new UnsupportedOperationException("Test exception");
- }
- }
-
- class DummyListener implements DecoratorListener {
-
- public boolean beforeCalled = false;
- public boolean afterCalled = false;
- public boolean catchCalled = false;
- public boolean finallyCalled = false;
- public Object resultValue = null;
-
- public boolean raiseException = false;
-
- @Override
- public void onBeforeInvocation(Method m, Object[] args) {
- beforeCalled = true;
- }
-
- @Override
- public void onAfterInvocation(Method m, Object[] args, Object result) {
- afterCalled = true;
- resultValue = result;
-
- if (raiseException) {
- throw new UnsupportedOperationException("Test exception");
- }
- }
-
- @Override
- public boolean onCatchException(Method m, Object[] args, Throwable t) {
- catchCalled = true;
- return false;
- }
-
- @Override
- public void onFinally(Method m, Object[] args) {
- finallyCalled = true;
- }
-
- };
-
- @SmallTest
- public void testDecorator() {
-
- // TODO rewrite this using mocks
-
- assertTrue(mIface.addValues(1, 2, 3) == 6);
- assertTrue(mDummyListener.beforeCalled);
- assertTrue(mDummyListener.afterCalled);
-
- int resultValue = (Integer)mDummyListener.resultValue;
- assertTrue(resultValue == 6);
- assertTrue(mDummyListener.finallyCalled);
- assertFalse(mDummyListener.catchCalled);
- }
-
- @SmallTest
- public void testDecoratorExceptions() {
-
- boolean gotExceptions = false;
- try {
- mIface.raiseException();
- } catch (Exception e) {
- gotExceptions = true;
- assertTrue(e.getMessage() == "Test exception");
- }
- assertTrue(gotExceptions);
- assertTrue(mDummyListener.beforeCalled);
- assertFalse(mDummyListener.afterCalled);
- assertTrue(mDummyListener.catchCalled);
- assertTrue(mDummyListener.finallyCalled);
- }
-
- @SmallTest
- public void testDecoratorUnsupportedOperationException() {
-
- boolean gotExceptions = false;
- try {
- mIface.raiseUnsupportedOperationException();
- } catch (UnsupportedOperationException e) {
- gotExceptions = true;
- assertTrue(e.getMessage() == "Test exception");
- }
- assertTrue(gotExceptions);
- assertTrue(mDummyListener.beforeCalled);
- assertFalse(mDummyListener.afterCalled);
- assertTrue(mDummyListener.catchCalled);
- assertTrue(mDummyListener.finallyCalled);
- }
-
- @SmallTest
- public void testDecoratorRaisesException() {
-
- boolean gotExceptions = false;
- try {
- mDummyListener.raiseException = true;
- mIface.addValues(1, 2, 3);
- Assert.fail("unreachable");
- } catch (UnsupportedOperationException e) {
- gotExceptions = true;
- assertTrue(e.getMessage() == "Test exception");
- }
- assertTrue(gotExceptions);
- assertTrue(mDummyListener.beforeCalled);
- assertTrue(mDummyListener.afterCalled);
- assertFalse(mDummyListener.catchCalled);
- assertTrue(mDummyListener.finallyCalled);
- }
-}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraUtilsRuntimeExceptionTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraUtilsRuntimeExceptionTest.java
deleted file mode 100644
index 02c9f2a..0000000
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraUtilsRuntimeExceptionTest.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright (C) 2013 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.mediaframeworktest.unit;
-
-import android.hardware.camera2.CameraAccessException;
-import android.hardware.camera2.utils.CameraRuntimeException;
-import android.hardware.camera2.utils.UncheckedThrow;
-import android.test.suitebuilder.annotation.SmallTest;
-
-import junit.framework.Assert;
-
-public class CameraUtilsRuntimeExceptionTest extends junit.framework.TestCase {
-
- @SmallTest
- public void testCameraRuntimeException1() {
- try {
- CameraRuntimeException runtimeExc = new CameraRuntimeException(12345);
- throw runtimeExc.asChecked();
- } catch (CameraAccessException e) {
- assertEquals(12345, e.getReason());
- assertNull(e.getMessage());
- assertNull(e.getCause());
- }
- }
-
- @SmallTest
- public void testCameraRuntimeException2() {
- try {
- CameraRuntimeException runtimeExc = new CameraRuntimeException(12345, "Hello");
- throw runtimeExc.asChecked();
- } catch (CameraAccessException e) {
- assertEquals(12345, e.getReason());
- assertEquals("Hello", e.getMessage());
- assertNull(e.getCause());
- }
- }
-
- @SmallTest
- public void testCameraRuntimeException3() {
- Throwable cause = new IllegalStateException("For great justice");
- try {
- CameraRuntimeException runtimeExc = new CameraRuntimeException(12345, cause);
- throw runtimeExc.asChecked();
- } catch (CameraAccessException e) {
- assertEquals(12345, e.getReason());
- assertNull(e.getMessage());
- assertEquals(cause, e.getCause());
- }
- }
-
- @SmallTest
- public void testCameraRuntimeException4() {
- Throwable cause = new IllegalStateException("For great justice");
- try {
- CameraRuntimeException runtimeExc = new CameraRuntimeException(12345, "Hello", cause);
- throw runtimeExc.asChecked();
- } catch (CameraAccessException e) {
- assertEquals(12345, e.getReason());
- assertEquals("Hello", e.getMessage());
- assertEquals(cause, e.getCause());
- }
- }
-}
diff --git a/packages/DocumentsUI/Android.mk b/packages/DocumentsUI/Android.mk
index 6dfc3bb..d5e48b5 100644
--- a/packages/DocumentsUI/Android.mk
+++ b/packages/DocumentsUI/Android.mk
@@ -38,5 +38,4 @@
LOCAL_CERTIFICATE := platform
include $(BUILD_PACKAGE)
-
-include $(LOCAL_PATH)/tests/Android.mk
+include $(call all-makefiles-under, $(LOCAL_PATH))
diff --git a/packages/DocumentsUI/perf-tests/Android.mk b/packages/DocumentsUI/perf-tests/Android.mk
new file mode 100644
index 0000000..c83094e
--- /dev/null
+++ b/packages/DocumentsUI/perf-tests/Android.mk
@@ -0,0 +1,22 @@
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+#LOCAL_SDK_VERSION := current
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src) \
+ $(call all-java-files-under, ../tests/src/com/android/documentsui/bots) \
+ ../tests/src/com/android/documentsui/ActivityTest.java \
+ ../tests/src/com/android/documentsui/DocumentsProviderHelper.java \
+ ../tests/src/com/android/documentsui/StubProvider.java
+
+LOCAL_JAVA_LIBRARIES := android.test.runner
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-v4 mockito-target ub-uiautomator
+
+LOCAL_PACKAGE_NAME := DocumentsUIPerfTests
+LOCAL_INSTRUMENTATION_FOR := DocumentsUI
+
+LOCAL_CERTIFICATE := platform
+
+include $(BUILD_PACKAGE)
+
diff --git a/packages/DocumentsUI/perf-tests/AndroidManifest.xml b/packages/DocumentsUI/perf-tests/AndroidManifest.xml
new file mode 100644
index 0000000..97353e7
--- /dev/null
+++ b/packages/DocumentsUI/perf-tests/AndroidManifest.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.documentsui.perftests">
+
+ <application>
+ <uses-library android:name="android.test.runner" />
+ <provider
+ android:name="com.android.documentsui.StressProvider"
+ android:authorities="com.android.documentsui.stressprovider"
+ android:exported="true"
+ android:grantUriPermissions="true"
+ android:permission="android.permission.MANAGE_DOCUMENTS"
+ android:enabled="true">
+ <intent-filter>
+ <action android:name="android.content.action.DOCUMENTS_PROVIDER" />
+ </intent-filter>
+ </provider>
+ </application>
+
+ <instrumentation android:name="android.test.InstrumentationTestRunner"
+ android:targetPackage="com.android.documentsui"
+ android:label="Performance tests for DocumentsUI" />
+
+</manifest>
diff --git a/packages/DocumentsUI/perf-tests/src/com/android/documentsui/FilesActivityPerfTest.java b/packages/DocumentsUI/perf-tests/src/com/android/documentsui/FilesActivityPerfTest.java
new file mode 100644
index 0000000..05fd2f7
--- /dev/null
+++ b/packages/DocumentsUI/perf-tests/src/com/android/documentsui/FilesActivityPerfTest.java
@@ -0,0 +1,143 @@
+/*
+ * 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.
+ */
+
+package com.android.documentsui;
+
+import static com.android.documentsui.StressProvider.DEFAULT_AUTHORITY;
+import static com.android.documentsui.StressProvider.STRESS_ROOT_0_ID;
+import static com.android.documentsui.StressProvider.STRESS_ROOT_1_ID;
+
+import android.app.Activity;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.RemoteException;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.util.Log;
+import android.view.KeyEvent;
+
+import com.android.documentsui.model.RootInfo;
+import com.android.documentsui.EventListener;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Random;
+import java.util.concurrent.CountDownLatch;
+
+@LargeTest
+public class FilesActivityPerfTest extends ActivityTest<FilesActivity> {
+
+ // Constants starting with KEY_ are used to report metrics to APCT.
+ private static final String KEY_FILES_LISTED_PERFORMANCE_FIRST =
+ "files-listed-performance-first";
+
+ private static final String KEY_FILES_LISTED_PERFORMANCE_MEDIAN =
+ "files-listed-performance-median";
+
+ private static final String TESTED_URI =
+ "content://com.android.documentsui.stressprovider/document/STRESS_ROOT_1_DOC";
+
+ private static final int NUM_MEASUREMENTS = 10;
+
+ public FilesActivityPerfTest() {
+ super(FilesActivity.class);
+ }
+
+ @Override
+ protected RootInfo getInitialRoot() {
+ return rootDir0;
+ }
+
+ @Override
+ protected String getTestingProviderAuthority() {
+ return DEFAULT_AUTHORITY;
+ }
+
+ @Override
+ protected void setupTestingRoots() throws RemoteException {
+ rootDir0 = mDocsHelper.getRoot(STRESS_ROOT_0_ID);
+ rootDir1 = mDocsHelper.getRoot(STRESS_ROOT_1_ID);
+ }
+
+ @Override
+ public void initTestFiles() throws RemoteException {
+ // Nothing to create, already done by StressProvider.
+ }
+
+ public void testFilesListedPerformance() throws Exception {
+ final BaseActivity activity = getActivity();
+
+ final List<Long> measurements = new ArrayList<Long>();
+ EventListener listener;
+ for (int i = 0; i < 10; i++) {
+ final CountDownLatch signal = new CountDownLatch(1);
+ listener = new EventListener() {
+ @Override
+ public void onDirectoryNavigated(Uri uri) {
+ if (uri != null && TESTED_URI.equals(uri.toString())) {
+ mStartTime = System.currentTimeMillis();
+ } else {
+ mStartTime = -1;
+ }
+ }
+
+ @Override
+ public void onDirectoryLoaded(Uri uri) {
+ if (uri == null || !TESTED_URI.equals(uri.toString())) {
+ return;
+ }
+ assertTrue(mStartTime != -1);
+ getInstrumentation().waitForIdle(new Runnable() {
+ @Override
+ public void run() {
+ assertTrue(mStartTime != -1);
+ measurements.add(System.currentTimeMillis() - mStartTime);
+ signal.countDown();
+ }
+ });
+ }
+
+ private long mStartTime = -1;
+ };
+
+ try {
+ activity.addEventListener(listener);
+ bots.roots.openRoot(STRESS_ROOT_1_ID);
+ signal.await();
+ } finally {
+ activity.removeEventListener(listener);
+ }
+
+ assertEquals(i, measurements.size());
+
+ // Go back to the empty root.
+ bots.roots.openRoot(STRESS_ROOT_0_ID);
+ }
+
+ assertEquals(NUM_MEASUREMENTS, measurements.size());
+
+ final Bundle status = new Bundle();
+ status.putDouble(KEY_FILES_LISTED_PERFORMANCE_FIRST, measurements.get(0));
+
+ final Long[] rawMeasurements = measurements.toArray(new Long[NUM_MEASUREMENTS]);
+ Arrays.sort(rawMeasurements);
+
+ final long median = rawMeasurements[NUM_MEASUREMENTS / 2 - 1];
+ status.putDouble(KEY_FILES_LISTED_PERFORMANCE_MEDIAN, median);
+
+ getInstrumentation().sendStatus(Activity.RESULT_OK, status);
+ }
+}
diff --git a/packages/DocumentsUI/perf-tests/src/com/android/documentsui/StressProvider.java b/packages/DocumentsUI/perf-tests/src/com/android/documentsui/StressProvider.java
new file mode 100644
index 0000000..1bc802a
--- /dev/null
+++ b/packages/DocumentsUI/perf-tests/src/com/android/documentsui/StressProvider.java
@@ -0,0 +1,149 @@
+/*
+ * 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.
+ */
+
+package com.android.documentsui;
+
+import android.content.Context;
+import android.content.pm.ProviderInfo;
+import android.database.Cursor;
+import android.database.MatrixCursor.RowBuilder;
+import android.database.MatrixCursor;
+import android.os.CancellationSignal;
+import android.os.FileUtils;
+import android.os.ParcelFileDescriptor;
+import android.provider.DocumentsContract.Document;
+import android.provider.DocumentsContract.Root;
+import android.provider.DocumentsContract;
+import android.provider.DocumentsProvider;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
+
+/**
+ * Provider with thousands of files for testing loading time of directories in DocumentsUI.
+ * It doesn't support any file operations.
+ */
+public class StressProvider extends DocumentsProvider {
+
+ public static final String DEFAULT_AUTHORITY = "com.android.documentsui.stressprovider";
+
+ // Empty root.
+ public static final String STRESS_ROOT_0_ID = "STRESS_ROOT_0";
+
+ // Root with thousands of items.
+ public static final String STRESS_ROOT_1_ID = "STRESS_ROOT_1";
+
+ private static final String STRESS_ROOT_0_DOC_ID = "STRESS_ROOT_0_DOC";
+ private static final String STRESS_ROOT_1_DOC_ID = "STRESS_ROOT_1_DOC";
+
+ private static final String[] DEFAULT_ROOT_PROJECTION = new String[] {
+ Root.COLUMN_ROOT_ID, Root.COLUMN_FLAGS, Root.COLUMN_TITLE, Root.COLUMN_DOCUMENT_ID,
+ Root.COLUMN_AVAILABLE_BYTES
+ };
+ private static final String[] DEFAULT_DOCUMENT_PROJECTION = new String[] {
+ Document.COLUMN_DOCUMENT_ID, Document.COLUMN_MIME_TYPE, Document.COLUMN_DISPLAY_NAME,
+ Document.COLUMN_LAST_MODIFIED, Document.COLUMN_FLAGS, Document.COLUMN_SIZE,
+ };
+
+ private String mAuthority = DEFAULT_AUTHORITY;
+ private ArrayList<String> mIds = new ArrayList<>();
+
+ @Override
+ public void attachInfo(Context context, ProviderInfo info) {
+ mAuthority = info.authority;
+ super.attachInfo(context, info);
+ }
+
+ @Override
+ public boolean onCreate() {
+ mIds = new ArrayList();
+ for (int i = 0; i < 10000; i++) {
+ mIds.add(createRandomId(i));
+ }
+ mIds.add(STRESS_ROOT_0_DOC_ID);
+ mIds.add(STRESS_ROOT_1_DOC_ID);
+ return true;
+ }
+
+ @Override
+ public Cursor queryRoots(String[] projection) throws FileNotFoundException {
+ final MatrixCursor result = new MatrixCursor(DEFAULT_ROOT_PROJECTION);
+ includeRoot(result, STRESS_ROOT_0_ID, STRESS_ROOT_0_DOC_ID);
+ includeRoot(result, STRESS_ROOT_1_ID, STRESS_ROOT_1_DOC_ID);
+ return result;
+ }
+
+ @Override
+ public Cursor queryDocument(String documentId, String[] projection)
+ throws FileNotFoundException {
+ final MatrixCursor result = new MatrixCursor(DEFAULT_DOCUMENT_PROJECTION);
+ includeDocument(result, documentId);
+ return result;
+ }
+
+ @Override
+ public Cursor queryChildDocuments(String parentDocumentId, String[] projection, String sortOrder)
+ throws FileNotFoundException {
+ final MatrixCursor result = new MatrixCursor(DEFAULT_DOCUMENT_PROJECTION);
+ if (STRESS_ROOT_1_DOC_ID.equals(parentDocumentId)) {
+ for (String id : mIds) {
+ includeDocument(result, id);
+ }
+ }
+ return result;
+ }
+
+ @Override
+ public ParcelFileDescriptor openDocument(String docId, String mode, CancellationSignal signal)
+ throws FileNotFoundException {
+ throw new UnsupportedOperationException();
+ }
+
+ private void includeRoot(MatrixCursor result, String rootId, String docId) {
+ final RowBuilder row = result.newRow();
+ row.add(Root.COLUMN_ROOT_ID, rootId);
+ row.add(Root.COLUMN_FLAGS, 0);
+ row.add(Root.COLUMN_TITLE, rootId);
+ row.add(Root.COLUMN_DOCUMENT_ID, docId);
+ }
+
+ private void includeDocument(MatrixCursor result, String id) {
+ final RowBuilder row = result.newRow();
+ row.add(Document.COLUMN_DOCUMENT_ID, id);
+ row.add(Document.COLUMN_DISPLAY_NAME, id);
+ row.add(Document.COLUMN_SIZE, 0);
+ row.add(Document.COLUMN_MIME_TYPE, DocumentsContract.Document.MIME_TYPE_DIR);
+ row.add(Document.COLUMN_FLAGS, 0);
+ row.add(Document.COLUMN_LAST_MODIFIED, null);
+ }
+
+ private static String getDocumentIdForFile(File file) {
+ return file.getAbsolutePath();
+ }
+
+ private String createRandomId(int index) {
+ final Random random = new Random(index);
+ final StringBuilder builder = new StringBuilder();
+ for (int i = 0; i < 20; i++) {
+ builder.append((char) (random.nextInt(96) + 32));
+ }
+ builder.append(index); // Append a number to guarantee uniqueness.
+ return builder.toString();
+ }
+}
diff --git a/packages/DocumentsUI/res/drawable/ic_sd_storage.xml b/packages/DocumentsUI/res/drawable/ic_sd_storage.xml
index b0f3cc3..5aeebbb 100644
--- a/packages/DocumentsUI/res/drawable/ic_sd_storage.xml
+++ b/packages/DocumentsUI/res/drawable/ic_sd_storage.xml
@@ -14,8 +14,8 @@
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="48dp"
- android:height="48dp"
+ android:width="24dp"
+ android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
diff --git a/packages/DocumentsUI/res/drawable/ic_usb_storage.xml b/packages/DocumentsUI/res/drawable/ic_usb_storage.xml
new file mode 100644
index 0000000..2a8d024
--- /dev/null
+++ b/packages/DocumentsUI/res/drawable/ic_usb_storage.xml
@@ -0,0 +1,24 @@
+<!--
+Copyright (C) 2015 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M15 7v4h1v2h-3V5h2l-3,-4,-3 4h2v8H8v-2.07c.7,-.37 1.2,-1.08 1.2,-1.93 0,-1.21,-.99,-2.2,-2.2,-2.2,-1.21 0,-2.2.99,-2.2 2.2 0 .85.5 1.56 1.2 1.93V13c0 1.11.89 2 2 2h3v3.05c-.71.37,-1.2 1.1,-1.2 1.95 0 1.22.99 2.2 2.2 2.2 1.21 0 2.2,-.98 2.2,-2.2 0,-.85,-.49,-1.58,-1.2,-1.95V15h3c1.11 0 2,-.89 2,-2v-2h1V7h-4z"/>
+</vector>
diff --git a/packages/DocumentsUI/res/layout/dialog_delete_confirmation.xml b/packages/DocumentsUI/res/layout/dialog_delete_confirmation.xml
new file mode 100644
index 0000000..990ce0b
--- /dev/null
+++ b/packages/DocumentsUI/res/layout/dialog_delete_confirmation.xml
@@ -0,0 +1,25 @@
+<?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.
+-->
+
+<TextView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:paddingTop="30dp"
+ android:gravity="center"
+ android:textAppearance="@android:style/TextAppearance.Material.Subhead"
+ android:textColor="@*android:color/primary_text_default_material_light">
+</TextView>
diff --git a/packages/DocumentsUI/res/layout/item_root.xml b/packages/DocumentsUI/res/layout/item_root.xml
index ff80d07..816cb8a 100644
--- a/packages/DocumentsUI/res/layout/item_root.xml
+++ b/packages/DocumentsUI/res/layout/item_root.xml
@@ -27,8 +27,6 @@
<FrameLayout
android:layout_width="@dimen/icon_size"
android:layout_height="@dimen/icon_size"
- android:layout_marginStart="@dimen/root_icon_margin"
- android:layout_marginEnd="@dimen/root_icon_margin"
android:duplicateParentState="true">
<ImageView
@@ -55,7 +53,7 @@
android:singleLine="true"
android:ellipsize="end"
android:textAlignment="viewStart"
- android:textAppearance="@android:style/TextAppearance.Material.Body1"
+ android:textAppearance="@android:style/TextAppearance.Material.Menu"
android:textColor="@color/item_root_primary_text" />
<TextView
@@ -65,7 +63,7 @@
android:singleLine="true"
android:ellipsize="end"
android:textAlignment="viewStart"
- android:textAppearance="@android:style/TextAppearance.Material.Body1"
+ android:textAppearance="@android:style/TextAppearance.Material.Caption"
android:textColor="@color/item_root_primary_text" />
</LinearLayout>
diff --git a/packages/DocumentsUI/res/menu/activity.xml b/packages/DocumentsUI/res/menu/activity.xml
index 73571af..79f6fa9 100644
--- a/packages/DocumentsUI/res/menu/activity.xml
+++ b/packages/DocumentsUI/res/menu/activity.xml
@@ -84,10 +84,6 @@
android:showAsAction="never"
android:visible="false" />
<item
- android:id="@+id/menu_advanced"
- android:showAsAction="never"
- android:visible="false" />
- <item
android:id="@+id/menu_settings"
android:title="@string/menu_settings"
android:showAsAction="never"
diff --git a/packages/DocumentsUI/res/values-af/strings.xml b/packages/DocumentsUI/res/values-af/strings.xml
index 9c66502..8846b62 100644
--- a/packages/DocumentsUI/res/values-af/strings.xml
+++ b/packages/DocumentsUI/res/values-af/strings.xml
@@ -67,8 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"Deel via"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"Kopieer tans lêers"</string>
<string name="move_notification_title" msgid="6193835179777284805">"Skuif tans lêers"</string>
- <!-- no translation found for delete_notification_title (3329403967712437496) -->
- <skip />
+ <string name="delete_notification_title" msgid="3329403967712437496">"Vee tans lêers uit"</string>
<string name="copy_remaining" msgid="6283790937387975095">"<xliff:g id="DURATION">%s</xliff:g> oor"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="other">Kopieer tans <xliff:g id="COUNT_1">%1$d</xliff:g> lêers.</item>
@@ -113,7 +112,9 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Sommige lêers is omgeskakel"</string>
<string name="allow" msgid="7225948811296386551">"Laat toe"</string>
<string name="deny" msgid="2081879885755434506">"Weier"</string>
- <!-- no translation found for delete_confirmation_title (1958369150786342998) -->
- <skip />
- <!-- no translation found for delete_confirmation_message (6608317554854868128) -->
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"Vee lêers uit?"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="other">Is jy seker jy wil <xliff:g id="COUNT_1">%1$d</xliff:g> lêers uitvee?</item>
+ <item quantity="one">Is jy seker jy wil <xliff:g id="COUNT_0">%1$d</xliff:g> lêer uitvee?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-am/strings.xml b/packages/DocumentsUI/res/values-am/strings.xml
index c255e36..6f975da 100644
--- a/packages/DocumentsUI/res/values-am/strings.xml
+++ b/packages/DocumentsUI/res/values-am/strings.xml
@@ -67,8 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"በሚከተለው በኩል ያጋሩ"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"ፋይሎች በመገልበጥ ላይ"</string>
<string name="move_notification_title" msgid="6193835179777284805">"ፋይሎችን በመውሰድ ላይ"</string>
- <!-- no translation found for delete_notification_title (3329403967712437496) -->
- <skip />
+ <string name="delete_notification_title" msgid="3329403967712437496">"ፋይሎችን በመሰረዝ ላይ"</string>
<string name="copy_remaining" msgid="6283790937387975095">"<xliff:g id="DURATION">%s</xliff:g> ቀርቷል"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> ፋይሎች በመቅዳት ላይ።</item>
@@ -113,7 +112,9 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"አንዳንድ ፋይሎች ተለውጠዋል"</string>
<string name="allow" msgid="7225948811296386551">"ይፍቀዱ"</string>
<string name="deny" msgid="2081879885755434506">"ያስተባብሉ"</string>
- <!-- no translation found for delete_confirmation_title (1958369150786342998) -->
- <skip />
- <!-- no translation found for delete_confirmation_message (6608317554854868128) -->
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"ፋይሎች ይሰረዙ?"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="one">እርግጠኛ ነዎት <xliff:g id="COUNT_1">%1$d</xliff:g> ፋይሎችን መሰረዝ ይፈልጋሉ?</item>
+ <item quantity="other">እርግጠኛ ነዎት <xliff:g id="COUNT_1">%1$d</xliff:g> ፋይሎችን መሰረዝ ይፈልጋሉ?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-b+sr+Latn/strings.xml b/packages/DocumentsUI/res/values-b+sr+Latn/strings.xml
index 81a4f9bd..ea4485b 100644
--- a/packages/DocumentsUI/res/values-b+sr+Latn/strings.xml
+++ b/packages/DocumentsUI/res/values-b+sr+Latn/strings.xml
@@ -67,8 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"Delite preko"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"Kopiranje datoteka"</string>
<string name="move_notification_title" msgid="6193835179777284805">"Datoteke se premeštaju"</string>
- <!-- no translation found for delete_notification_title (3329403967712437496) -->
- <skip />
+ <string name="delete_notification_title" msgid="3329403967712437496">"Datoteke se brišu"</string>
<string name="copy_remaining" msgid="6283790937387975095">"Još <xliff:g id="DURATION">%s</xliff:g>"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="one">Kopiranje <xliff:g id="COUNT_1">%1$d</xliff:g> datoteke.</item>
@@ -120,7 +119,10 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Neke datoteke su konvertovane"</string>
<string name="allow" msgid="7225948811296386551">"Dozvoli"</string>
<string name="deny" msgid="2081879885755434506">"Odbij"</string>
- <!-- no translation found for delete_confirmation_title (1958369150786342998) -->
- <skip />
- <!-- no translation found for delete_confirmation_message (6608317554854868128) -->
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"Želite li da izbrišete datoteke?"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="one">Želite li stvarno da izbrišete <xliff:g id="COUNT_1">%1$d</xliff:g> datoteku?</item>
+ <item quantity="few">Želite li stvarno da izbrišete <xliff:g id="COUNT_1">%1$d</xliff:g> datoteke?</item>
+ <item quantity="other">Želite li stvarno da izbrišete <xliff:g id="COUNT_1">%1$d</xliff:g> datoteka?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-bg/strings.xml b/packages/DocumentsUI/res/values-bg/strings.xml
index 7c096d9..66af887 100644
--- a/packages/DocumentsUI/res/values-bg/strings.xml
+++ b/packages/DocumentsUI/res/values-bg/strings.xml
@@ -67,8 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"Споделяне чрез"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"Файловете се копират"</string>
<string name="move_notification_title" msgid="6193835179777284805">"Файловете се преместват"</string>
- <!-- no translation found for delete_notification_title (3329403967712437496) -->
- <skip />
+ <string name="delete_notification_title" msgid="3329403967712437496">"Изтриване на файлове"</string>
<string name="copy_remaining" msgid="6283790937387975095">"Оставащо време: <xliff:g id="DURATION">%s</xliff:g>"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="other">Копират се <xliff:g id="COUNT_1">%1$d</xliff:g> файла.</item>
@@ -113,7 +112,9 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Някои файлове бяха преобразувани"</string>
<string name="allow" msgid="7225948811296386551">"Разрешаване"</string>
<string name="deny" msgid="2081879885755434506">"Отказване"</string>
- <!-- no translation found for delete_confirmation_title (1958369150786342998) -->
- <skip />
- <!-- no translation found for delete_confirmation_message (6608317554854868128) -->
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"Да се изтрият ли файловете?"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="other">Наистина ли искате да изтриете <xliff:g id="COUNT_1">%1$d</xliff:g> файла?</item>
+ <item quantity="one">Наистина ли искате да изтриете <xliff:g id="COUNT_0">%1$d</xliff:g> файл?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-bs-rBA/strings.xml b/packages/DocumentsUI/res/values-bs-rBA/strings.xml
index 68a2b42..9f5f932 100644
--- a/packages/DocumentsUI/res/values-bs-rBA/strings.xml
+++ b/packages/DocumentsUI/res/values-bs-rBA/strings.xml
@@ -67,8 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"Podijeli preko"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"Kopiraju se fajlovi"</string>
<string name="move_notification_title" msgid="6193835179777284805">"Premještanje fajlova"</string>
- <!-- no translation found for delete_notification_title (3329403967712437496) -->
- <skip />
+ <string name="delete_notification_title" msgid="3329403967712437496">"Brisanje fajlova"</string>
<string name="copy_remaining" msgid="6283790937387975095">"Još <xliff:g id="DURATION">%s</xliff:g>"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="one">Kopira se <xliff:g id="COUNT_1">%1$d</xliff:g> fajl.</item>
@@ -120,7 +119,10 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Neke od datoteka su pretvorene"</string>
<string name="allow" msgid="7225948811296386551">"Dozvoli"</string>
<string name="deny" msgid="2081879885755434506">"Odbijte"</string>
- <!-- no translation found for delete_confirmation_title (1958369150786342998) -->
- <skip />
- <!-- no translation found for delete_confirmation_message (6608317554854868128) -->
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"Zaista želite obrisati fajlove?"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="one"> Jeste li sigurni da želite izbrisati <xliff:g id="COUNT_1">%1$d</xliff:g> fajl?</item>
+ <item quantity="few"> Jeste li sigurni da želite izbrisati <xliff:g id="COUNT_1">%1$d</xliff:g> fajla?</item>
+ <item quantity="other"> Jeste li sigurni da želite izbrisati <xliff:g id="COUNT_1">%1$d</xliff:g> fajlova?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-ca/strings.xml b/packages/DocumentsUI/res/values-ca/strings.xml
index e979b11..2b136f1 100644
--- a/packages/DocumentsUI/res/values-ca/strings.xml
+++ b/packages/DocumentsUI/res/values-ca/strings.xml
@@ -67,8 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"Comparteix mitjançant"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"S\'estan copiant fitxers"</string>
<string name="move_notification_title" msgid="6193835179777284805">"S\'estan movent fitxers"</string>
- <!-- no translation found for delete_notification_title (3329403967712437496) -->
- <skip />
+ <string name="delete_notification_title" msgid="3329403967712437496">"Suprimint els fitxers"</string>
<string name="copy_remaining" msgid="6283790937387975095">"Temps restant: <xliff:g id="DURATION">%s</xliff:g>"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="other">S\'estan copiant <xliff:g id="COUNT_1">%1$d</xliff:g> fitxers.</item>
@@ -113,7 +112,9 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"S\'han convertit alguns fitxers"</string>
<string name="allow" msgid="7225948811296386551">"Permet"</string>
<string name="deny" msgid="2081879885755434506">"Denega"</string>
- <!-- no translation found for delete_confirmation_title (1958369150786342998) -->
- <skip />
- <!-- no translation found for delete_confirmation_message (6608317554854868128) -->
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"Vols suprimir els fitxers?"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="other">Confirmes que vols suprimir <xliff:g id="COUNT_1">%1$d</xliff:g> fitxers?</item>
+ <item quantity="one">Confirmes que vols suprimir <xliff:g id="COUNT_0">%1$d</xliff:g> fitxer?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-cs/strings.xml b/packages/DocumentsUI/res/values-cs/strings.xml
index 0f3b4e0..7196c6a 100644
--- a/packages/DocumentsUI/res/values-cs/strings.xml
+++ b/packages/DocumentsUI/res/values-cs/strings.xml
@@ -67,8 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"Sdílet pomocí"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"Kopírování souborů"</string>
<string name="move_notification_title" msgid="6193835179777284805">"Přesouvání souborů"</string>
- <!-- no translation found for delete_notification_title (3329403967712437496) -->
- <skip />
+ <string name="delete_notification_title" msgid="3329403967712437496">"Mazání souborů"</string>
<string name="copy_remaining" msgid="6283790937387975095">"Zbývající čas: <xliff:g id="DURATION">%s</xliff:g>"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="few">Kopírování <xliff:g id="COUNT_1">%1$d</xliff:g> souborů</item>
@@ -127,7 +126,11 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Některé soubory byly převedeny"</string>
<string name="allow" msgid="7225948811296386551">"Povolit"</string>
<string name="deny" msgid="2081879885755434506">"Odepřít"</string>
- <!-- no translation found for delete_confirmation_title (1958369150786342998) -->
- <skip />
- <!-- no translation found for delete_confirmation_message (6608317554854868128) -->
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"Smazat soubory?"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="few">Opravdu chcete smazat <xliff:g id="COUNT_1">%1$d</xliff:g> soubory?</item>
+ <item quantity="many">Opravdu chcete smazat <xliff:g id="COUNT_1">%1$d</xliff:g> souboru?</item>
+ <item quantity="other">Opravdu chcete smazat <xliff:g id="COUNT_1">%1$d</xliff:g> souborů?</item>
+ <item quantity="one">Opravdu chcete smazat <xliff:g id="COUNT_0">%1$d</xliff:g> soubor?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-da/strings.xml b/packages/DocumentsUI/res/values-da/strings.xml
index 3854f0f..ab9271c 100644
--- a/packages/DocumentsUI/res/values-da/strings.xml
+++ b/packages/DocumentsUI/res/values-da/strings.xml
@@ -67,8 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"Del via"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"Kopierer filer"</string>
<string name="move_notification_title" msgid="6193835179777284805">"Flytter filer"</string>
- <!-- no translation found for delete_notification_title (3329403967712437496) -->
- <skip />
+ <string name="delete_notification_title" msgid="3329403967712437496">"Filerne slettes"</string>
<string name="copy_remaining" msgid="6283790937387975095">"<xliff:g id="DURATION">%s</xliff:g> tilbage"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="one">Kopierer <xliff:g id="COUNT_1">%1$d</xliff:g> filer.</item>
@@ -113,7 +112,9 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Nogle filer er konverteret"</string>
<string name="allow" msgid="7225948811296386551">"Tillad"</string>
<string name="deny" msgid="2081879885755434506">"Afvis"</string>
- <!-- no translation found for delete_confirmation_title (1958369150786342998) -->
- <skip />
- <!-- no translation found for delete_confirmation_message (6608317554854868128) -->
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"Vil du slette filerne?"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="one">Er du sikker på, at du vil slette <xliff:g id="COUNT_1">%1$d</xliff:g> fil?</item>
+ <item quantity="other">Er du sikker på, at du vil slette <xliff:g id="COUNT_1">%1$d</xliff:g> filer?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-de/strings.xml b/packages/DocumentsUI/res/values-de/strings.xml
index fd7f35c..8c06c7f 100644
--- a/packages/DocumentsUI/res/values-de/strings.xml
+++ b/packages/DocumentsUI/res/values-de/strings.xml
@@ -67,8 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"Teilen über"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"Dateien werden kopiert"</string>
<string name="move_notification_title" msgid="6193835179777284805">"Dateien werden verschoben"</string>
- <!-- no translation found for delete_notification_title (3329403967712437496) -->
- <skip />
+ <string name="delete_notification_title" msgid="3329403967712437496">"Dateien werden gelöscht"</string>
<string name="copy_remaining" msgid="6283790937387975095">"Noch <xliff:g id="DURATION">%s</xliff:g>"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> Dateien werden kopiert.</item>
@@ -113,7 +112,9 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Einige Dateien wurden konvertiert"</string>
<string name="allow" msgid="7225948811296386551">"Zulassen"</string>
<string name="deny" msgid="2081879885755434506">"Ablehnen"</string>
- <!-- no translation found for delete_confirmation_title (1958369150786342998) -->
- <skip />
- <!-- no translation found for delete_confirmation_message (6608317554854868128) -->
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"Dateien löschen?"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="other">Möchtest du wirklich <xliff:g id="COUNT_1">%1$d</xliff:g> Dateien löschen?</item>
+ <item quantity="one">Möchtest du wirklich <xliff:g id="COUNT_0">%1$d</xliff:g> Datei löschen?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-el/strings.xml b/packages/DocumentsUI/res/values-el/strings.xml
index 6257e17..1752a29 100644
--- a/packages/DocumentsUI/res/values-el/strings.xml
+++ b/packages/DocumentsUI/res/values-el/strings.xml
@@ -67,8 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"Κοινή χρήση μέσω"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"Αντιγραφή αρχείων"</string>
<string name="move_notification_title" msgid="6193835179777284805">"Μετακίνηση αρχείων"</string>
- <!-- no translation found for delete_notification_title (3329403967712437496) -->
- <skip />
+ <string name="delete_notification_title" msgid="3329403967712437496">"Διαγραφή αρχείων"</string>
<string name="copy_remaining" msgid="6283790937387975095">"Απομένουν <xliff:g id="DURATION">%s</xliff:g>"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="other">Αντιγραφή <xliff:g id="COUNT_1">%1$d</xliff:g> αρχείων.</item>
@@ -113,7 +112,9 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Ορισμένα αρχεία μετατράπηκαν"</string>
<string name="allow" msgid="7225948811296386551">"Να επιτρέπεται"</string>
<string name="deny" msgid="2081879885755434506">"Άρνηση"</string>
- <!-- no translation found for delete_confirmation_title (1958369150786342998) -->
- <skip />
- <!-- no translation found for delete_confirmation_message (6608317554854868128) -->
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"Διαγραφή αρχείων;"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="other">Είστε βέβαιοι ότι θέλετε να διαγράψετε <xliff:g id="COUNT_1">%1$d</xliff:g> αρχεία;</item>
+ <item quantity="one">Είστε βέβαιοι ότι θέλετε να διαγράψετε <xliff:g id="COUNT_0">%1$d</xliff:g> αρχείο;</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-es-rUS/strings.xml b/packages/DocumentsUI/res/values-es-rUS/strings.xml
index 29b9111..1ba7c2d 100644
--- a/packages/DocumentsUI/res/values-es-rUS/strings.xml
+++ b/packages/DocumentsUI/res/values-es-rUS/strings.xml
@@ -67,8 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"Compartir mediante"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"Copiando archivos"</string>
<string name="move_notification_title" msgid="6193835179777284805">"Moviendo archivos"</string>
- <!-- no translation found for delete_notification_title (3329403967712437496) -->
- <skip />
+ <string name="delete_notification_title" msgid="3329403967712437496">"Borrando los archivos"</string>
<string name="copy_remaining" msgid="6283790937387975095">"Faltan <xliff:g id="DURATION">%s</xliff:g>."</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="other">Copiando <xliff:g id="COUNT_1">%1$d</xliff:g> archivos</item>
@@ -113,7 +112,9 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Se convirtieron algunos archivos"</string>
<string name="allow" msgid="7225948811296386551">"Permitir"</string>
<string name="deny" msgid="2081879885755434506">"Denegar"</string>
- <!-- no translation found for delete_confirmation_title (1958369150786342998) -->
- <skip />
- <!-- no translation found for delete_confirmation_message (6608317554854868128) -->
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"¿Quieres borrar los archivos?"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="other">¿Confirmas que quieres borrar <xliff:g id="COUNT_1">%1$d</xliff:g> archivos?</item>
+ <item quantity="one">¿Confirmas que quieres borrar <xliff:g id="COUNT_0">%1$d</xliff:g> archivo?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-es/strings.xml b/packages/DocumentsUI/res/values-es/strings.xml
index 02e6d74..0c1f2dd 100644
--- a/packages/DocumentsUI/res/values-es/strings.xml
+++ b/packages/DocumentsUI/res/values-es/strings.xml
@@ -67,8 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"Compartir a través de"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"Copiando archivos"</string>
<string name="move_notification_title" msgid="6193835179777284805">"Moviendo archivos"</string>
- <!-- no translation found for delete_notification_title (3329403967712437496) -->
- <skip />
+ <string name="delete_notification_title" msgid="3329403967712437496">"Eliminando archivos"</string>
<string name="copy_remaining" msgid="6283790937387975095">"Tiempo restante: <xliff:g id="DURATION">%s</xliff:g>"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="other">Copiando <xliff:g id="COUNT_1">%1$d</xliff:g> archivos.</item>
@@ -113,7 +112,9 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Se han convertido algunos archivos"</string>
<string name="allow" msgid="7225948811296386551">"Permitir"</string>
<string name="deny" msgid="2081879885755434506">"Denegar"</string>
- <!-- no translation found for delete_confirmation_title (1958369150786342998) -->
- <skip />
- <!-- no translation found for delete_confirmation_message (6608317554854868128) -->
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"¿Eliminar archivos?"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="other">¿Seguro que quieres eliminar <xliff:g id="COUNT_1">%1$d</xliff:g> archivos?</item>
+ <item quantity="one">¿Seguro que quieres eliminar <xliff:g id="COUNT_0">%1$d</xliff:g> archivo?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-eu-rES/strings.xml b/packages/DocumentsUI/res/values-eu-rES/strings.xml
index 125d899..c66bae4 100644
--- a/packages/DocumentsUI/res/values-eu-rES/strings.xml
+++ b/packages/DocumentsUI/res/values-eu-rES/strings.xml
@@ -67,8 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"Partekatu honen bidez:"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"Fitxategiak kopiatzen"</string>
<string name="move_notification_title" msgid="6193835179777284805">"Fitxategiak mugitzea"</string>
- <!-- no translation found for delete_notification_title (3329403967712437496) -->
- <skip />
+ <string name="delete_notification_title" msgid="3329403967712437496">"Fitxategiak ezabatzea"</string>
<string name="copy_remaining" msgid="6283790937387975095">"Falta den denbora: <xliff:g id="DURATION">%s</xliff:g>"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> fitxategi kopiatzen.</item>
@@ -113,7 +112,9 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Artxibo batzuk bihurtu dira"</string>
<string name="allow" msgid="7225948811296386551">"Onartu"</string>
<string name="deny" msgid="2081879885755434506">"Ukatu"</string>
- <!-- no translation found for delete_confirmation_title (1958369150786342998) -->
- <skip />
- <!-- no translation found for delete_confirmation_message (6608317554854868128) -->
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"Fitxategiak ezabatu nahi dituzu?"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="other">Ziur <xliff:g id="COUNT_1">%1$d</xliff:g> fitxategi ezabatu nahi dituzula?</item>
+ <item quantity="one">Ziur <xliff:g id="COUNT_0">%1$d</xliff:g> fitxategi ezabatu nahi duzula?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-fi/strings.xml b/packages/DocumentsUI/res/values-fi/strings.xml
index 0788598..1dfbe15 100644
--- a/packages/DocumentsUI/res/values-fi/strings.xml
+++ b/packages/DocumentsUI/res/values-fi/strings.xml
@@ -67,8 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"Jaa sovelluksessa"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"Kopioidaan tiedostoja"</string>
<string name="move_notification_title" msgid="6193835179777284805">"Siirretään tiedostoja"</string>
- <!-- no translation found for delete_notification_title (3329403967712437496) -->
- <skip />
+ <string name="delete_notification_title" msgid="3329403967712437496">"Poistetaan tiedostoja"</string>
<string name="copy_remaining" msgid="6283790937387975095">"<xliff:g id="DURATION">%s</xliff:g> jäljellä"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="other">Kopioidaan <xliff:g id="COUNT_1">%1$d</xliff:g> tiedostoa.</item>
@@ -113,7 +112,9 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Joitakin tiedostoja muunnettiin."</string>
<string name="allow" msgid="7225948811296386551">"Salli"</string>
<string name="deny" msgid="2081879885755434506">"Kiellä"</string>
- <!-- no translation found for delete_confirmation_title (1958369150786342998) -->
- <skip />
- <!-- no translation found for delete_confirmation_message (6608317554854868128) -->
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"Poistetaanko tiedostot?"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="other">Haluatko varmasti poistaa <xliff:g id="COUNT_1">%1$d</xliff:g> tiedostoa?</item>
+ <item quantity="one">Haluatko varmasti poistaa <xliff:g id="COUNT_0">%1$d</xliff:g> tiedoston?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-fr-rCA/strings.xml b/packages/DocumentsUI/res/values-fr-rCA/strings.xml
index 6b4c7fd..08dacac 100644
--- a/packages/DocumentsUI/res/values-fr-rCA/strings.xml
+++ b/packages/DocumentsUI/res/values-fr-rCA/strings.xml
@@ -67,8 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"Partager par"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"Copie de fichiers..."</string>
<string name="move_notification_title" msgid="6193835179777284805">"Déplacement des fichiers"</string>
- <!-- no translation found for delete_notification_title (3329403967712437496) -->
- <skip />
+ <string name="delete_notification_title" msgid="3329403967712437496">"Suppression des fichiers"</string>
<string name="copy_remaining" msgid="6283790937387975095">"Durée restante : <xliff:g id="DURATION">%s</xliff:g>"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="one">Copier de <xliff:g id="COUNT_1">%1$d</xliff:g> fichier en cours.</item>
@@ -113,7 +112,9 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Certains fichiers ont été convertis"</string>
<string name="allow" msgid="7225948811296386551">"Autoriser"</string>
<string name="deny" msgid="2081879885755434506">"Refuser"</string>
- <!-- no translation found for delete_confirmation_title (1958369150786342998) -->
- <skip />
- <!-- no translation found for delete_confirmation_message (6608317554854868128) -->
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"Supprimer les fichiers?"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="one">Voulez-vous vraiment supprimer <xliff:g id="COUNT_1">%1$d</xliff:g> fichier?</item>
+ <item quantity="other">Voulez-vous vraiment supprimer <xliff:g id="COUNT_1">%1$d</xliff:g> fichiers?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-fr/strings.xml b/packages/DocumentsUI/res/values-fr/strings.xml
index 84021b0..6378191 100644
--- a/packages/DocumentsUI/res/values-fr/strings.xml
+++ b/packages/DocumentsUI/res/values-fr/strings.xml
@@ -67,8 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"Partager via"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"Copie de fichiers en cours"</string>
<string name="move_notification_title" msgid="6193835179777284805">"Déplacement de fichiers"</string>
- <!-- no translation found for delete_notification_title (3329403967712437496) -->
- <skip />
+ <string name="delete_notification_title" msgid="3329403967712437496">"Suppression des fichiers…"</string>
<string name="copy_remaining" msgid="6283790937387975095">"Temps restant : <xliff:g id="DURATION">%s</xliff:g>"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="one">Copie de <xliff:g id="COUNT_1">%1$d</xliff:g> fichier en cours…</item>
@@ -113,7 +112,9 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Certains fichiers ont été convertis"</string>
<string name="allow" msgid="7225948811296386551">"Autoriser"</string>
<string name="deny" msgid="2081879885755434506">"Refuser"</string>
- <!-- no translation found for delete_confirmation_title (1958369150786342998) -->
- <skip />
- <!-- no translation found for delete_confirmation_message (6608317554854868128) -->
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"Supprimer les fichiers ?"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="one">Voulez-vous vraiment supprimer <xliff:g id="COUNT_1">%1$d</xliff:g> fichier ?</item>
+ <item quantity="other">Voulez-vous vraiment supprimer <xliff:g id="COUNT_1">%1$d</xliff:g> fichiers ?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-gl-rES/strings.xml b/packages/DocumentsUI/res/values-gl-rES/strings.xml
index fd03af7..79cc70f 100644
--- a/packages/DocumentsUI/res/values-gl-rES/strings.xml
+++ b/packages/DocumentsUI/res/values-gl-rES/strings.xml
@@ -67,8 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"Compartir a través de"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"Copiando ficheiros"</string>
<string name="move_notification_title" msgid="6193835179777284805">"Mover ficheiros"</string>
- <!-- no translation found for delete_notification_title (3329403967712437496) -->
- <skip />
+ <string name="delete_notification_title" msgid="3329403967712437496">"Eliminando ficheiros"</string>
<string name="copy_remaining" msgid="6283790937387975095">"Tempo restante: <xliff:g id="DURATION">%s</xliff:g>"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="other">Copiando <xliff:g id="COUNT_1">%1$d</xliff:g> ficheiros.</item>
@@ -113,7 +112,9 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Convertéronse algúns ficheiros"</string>
<string name="allow" msgid="7225948811296386551">"Permitir"</string>
<string name="deny" msgid="2081879885755434506">"Rexeitar"</string>
- <!-- no translation found for delete_confirmation_title (1958369150786342998) -->
- <skip />
- <!-- no translation found for delete_confirmation_message (6608317554854868128) -->
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"Queres eliminar os ficheiros?"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="other">Seguro que queres eliminar <xliff:g id="COUNT_1">%1$d</xliff:g> ficheiros?</item>
+ <item quantity="one">Seguro que queres eliminar <xliff:g id="COUNT_0">%1$d</xliff:g> ficheiro?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-hy-rAM/strings.xml b/packages/DocumentsUI/res/values-hy-rAM/strings.xml
index 2ad2aa7..3598934 100644
--- a/packages/DocumentsUI/res/values-hy-rAM/strings.xml
+++ b/packages/DocumentsUI/res/values-hy-rAM/strings.xml
@@ -67,8 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"Տարածել"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"Ֆայլերի պատճենում"</string>
<string name="move_notification_title" msgid="6193835179777284805">"Ֆայլերի տեղափոխում"</string>
- <!-- no translation found for delete_notification_title (3329403967712437496) -->
- <skip />
+ <string name="delete_notification_title" msgid="3329403967712437496">"Ֆայլերը ջնջվում են"</string>
<string name="copy_remaining" msgid="6283790937387975095">"Մնացել է <xliff:g id="DURATION">%s</xliff:g>"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> ֆայլի պատճենում:</item>
@@ -113,7 +112,9 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Որոշ ֆայլեր փոխարկվել են"</string>
<string name="allow" msgid="7225948811296386551">"Թույլատրել"</string>
<string name="deny" msgid="2081879885755434506">"Մերժել"</string>
- <!-- no translation found for delete_confirmation_title (1958369150786342998) -->
- <skip />
- <!-- no translation found for delete_confirmation_message (6608317554854868128) -->
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"Ջնջե՞լ ֆայլերը:"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="one">Ջնջե՞լ <xliff:g id="COUNT_1">%1$d</xliff:g> ֆայլ:</item>
+ <item quantity="other">Ջնջե՞լ <xliff:g id="COUNT_1">%1$d</xliff:g> ֆայլ:</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-in/strings.xml b/packages/DocumentsUI/res/values-in/strings.xml
index 66d40d2..d87fad3 100644
--- a/packages/DocumentsUI/res/values-in/strings.xml
+++ b/packages/DocumentsUI/res/values-in/strings.xml
@@ -67,8 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"Bagikan melalui"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"Menyalin file"</string>
<string name="move_notification_title" msgid="6193835179777284805">"Memindahkan file"</string>
- <!-- no translation found for delete_notification_title (3329403967712437496) -->
- <skip />
+ <string name="delete_notification_title" msgid="3329403967712437496">"Menghapus file"</string>
<string name="copy_remaining" msgid="6283790937387975095">"<xliff:g id="DURATION">%s</xliff:g> lagi"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="other">Menyalin <xliff:g id="COUNT_1">%1$d</xliff:g> file.</item>
@@ -113,7 +112,9 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Beberapa file dikonversi"</string>
<string name="allow" msgid="7225948811296386551">"Izinkan"</string>
<string name="deny" msgid="2081879885755434506">"Tolak"</string>
- <!-- no translation found for delete_confirmation_title (1958369150786342998) -->
- <skip />
- <!-- no translation found for delete_confirmation_message (6608317554854868128) -->
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"Hapus file?"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="other">Yakin ingin menghapus <xliff:g id="COUNT_1">%1$d</xliff:g> file?</item>
+ <item quantity="one">Yakin ingin menghapus <xliff:g id="COUNT_0">%1$d</xliff:g> file?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-is-rIS/strings.xml b/packages/DocumentsUI/res/values-is-rIS/strings.xml
index 290ec92..5b2531d 100644
--- a/packages/DocumentsUI/res/values-is-rIS/strings.xml
+++ b/packages/DocumentsUI/res/values-is-rIS/strings.xml
@@ -67,8 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"Deila í gegnum"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"Afritar skrár"</string>
<string name="move_notification_title" msgid="6193835179777284805">"Skrár færðar"</string>
- <!-- no translation found for delete_notification_title (3329403967712437496) -->
- <skip />
+ <string name="delete_notification_title" msgid="3329403967712437496">"Eyðir skrám"</string>
<string name="copy_remaining" msgid="6283790937387975095">"<xliff:g id="DURATION">%s</xliff:g> eftir"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="one">Afritar <xliff:g id="COUNT_1">%1$d</xliff:g> skrá.</item>
@@ -113,7 +112,9 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Sumum skrám var umbreytt"</string>
<string name="allow" msgid="7225948811296386551">"Leyfa"</string>
<string name="deny" msgid="2081879885755434506">"Hafna"</string>
- <!-- no translation found for delete_confirmation_title (1958369150786342998) -->
- <skip />
- <!-- no translation found for delete_confirmation_message (6608317554854868128) -->
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"Eyða skrám?"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="one">Ertu viss um að þú viljir eyða <xliff:g id="COUNT_1">%1$d</xliff:g> skrá?</item>
+ <item quantity="other">Ertu viss um að þú viljir eyða <xliff:g id="COUNT_1">%1$d</xliff:g> skrám?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-it/strings.xml b/packages/DocumentsUI/res/values-it/strings.xml
index 43f5fcb..4785ffc 100644
--- a/packages/DocumentsUI/res/values-it/strings.xml
+++ b/packages/DocumentsUI/res/values-it/strings.xml
@@ -67,8 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"Condividi via"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"Copia di file in corso"</string>
<string name="move_notification_title" msgid="6193835179777284805">"Spostamento di file"</string>
- <!-- no translation found for delete_notification_title (3329403967712437496) -->
- <skip />
+ <string name="delete_notification_title" msgid="3329403967712437496">"Eliminazione dei file"</string>
<string name="copy_remaining" msgid="6283790937387975095">"<xliff:g id="DURATION">%s</xliff:g> rimanenti"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="other">Copia di <xliff:g id="COUNT_1">%1$d</xliff:g> file in corso.</item>
@@ -113,7 +112,9 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Alcuni file sono stati convertiti"</string>
<string name="allow" msgid="7225948811296386551">"Consenti"</string>
<string name="deny" msgid="2081879885755434506">"Nega"</string>
- <!-- no translation found for delete_confirmation_title (1958369150786342998) -->
- <skip />
- <!-- no translation found for delete_confirmation_message (6608317554854868128) -->
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"Eliminare i file?"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="other">Vuoi eliminare <xliff:g id="COUNT_1">%1$d</xliff:g> file?</item>
+ <item quantity="one">Vuoi eliminare <xliff:g id="COUNT_0">%1$d</xliff:g> file?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-iw/strings.xml b/packages/DocumentsUI/res/values-iw/strings.xml
index 622785c..1fb81dd 100644
--- a/packages/DocumentsUI/res/values-iw/strings.xml
+++ b/packages/DocumentsUI/res/values-iw/strings.xml
@@ -67,8 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"שתף באמצעות"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"מעתיק קבצים"</string>
<string name="move_notification_title" msgid="6193835179777284805">"מעביר קבצים"</string>
- <!-- no translation found for delete_notification_title (3329403967712437496) -->
- <skip />
+ <string name="delete_notification_title" msgid="3329403967712437496">"מחיקת קבצים מתבצעת"</string>
<string name="copy_remaining" msgid="6283790937387975095">"זמן נותר: <xliff:g id="DURATION">%s</xliff:g>"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="two">מעתיק <xliff:g id="COUNT_1">%1$d</xliff:g> קבצים.</item>
@@ -127,7 +126,11 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"קבצים מסוימים הומרו"</string>
<string name="allow" msgid="7225948811296386551">"אפשר"</string>
<string name="deny" msgid="2081879885755434506">"דחה"</string>
- <!-- no translation found for delete_confirmation_title (1958369150786342998) -->
- <skip />
- <!-- no translation found for delete_confirmation_message (6608317554854868128) -->
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"האם למחוק את הקבצים?"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="two">האם אתה בטוח שברצונך למחוק <xliff:g id="COUNT_1">%1$d</xliff:g> קבצים?</item>
+ <item quantity="many">האם אתה בטוח שברצונך למחוק <xliff:g id="COUNT_1">%1$d</xliff:g> קבצים?</item>
+ <item quantity="other">האם אתה בטוח שברצונך למחוק <xliff:g id="COUNT_1">%1$d</xliff:g> קבצים?</item>
+ <item quantity="one">האם אתה בטוח שברצונך למחוק קובץ <xliff:g id="COUNT_0">%1$d</xliff:g>?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-ja/strings.xml b/packages/DocumentsUI/res/values-ja/strings.xml
index 3319af0..32bc414 100644
--- a/packages/DocumentsUI/res/values-ja/strings.xml
+++ b/packages/DocumentsUI/res/values-ja/strings.xml
@@ -67,8 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"共有ツール"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"ファイルのコピー中"</string>
<string name="move_notification_title" msgid="6193835179777284805">"ファイルを移動中"</string>
- <!-- no translation found for delete_notification_title (3329403967712437496) -->
- <skip />
+ <string name="delete_notification_title" msgid="3329403967712437496">"ファイルを削除しています"</string>
<string name="copy_remaining" msgid="6283790937387975095">"残り<xliff:g id="DURATION">%s</xliff:g>"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g>個のファイルをコピーしています。</item>
@@ -113,7 +112,9 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"一部のファイルが変換されました"</string>
<string name="allow" msgid="7225948811296386551">"許可"</string>
<string name="deny" msgid="2081879885755434506">"拒否"</string>
- <!-- no translation found for delete_confirmation_title (1958369150786342998) -->
- <skip />
- <!-- no translation found for delete_confirmation_message (6608317554854868128) -->
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"ファイルを削除しますか?"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> 個のファイルを削除してもよろしいですか?</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> 個のファイルを削除してもよろしいですか?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-ka-rGE/strings.xml b/packages/DocumentsUI/res/values-ka-rGE/strings.xml
index 30b78e5..ce32f23 100644
--- a/packages/DocumentsUI/res/values-ka-rGE/strings.xml
+++ b/packages/DocumentsUI/res/values-ka-rGE/strings.xml
@@ -67,8 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"გაზიარება:"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"მიმდ. ფაილების კოპირება"</string>
<string name="move_notification_title" msgid="6193835179777284805">"ფაილების გადაადგილება"</string>
- <!-- no translation found for delete_notification_title (3329403967712437496) -->
- <skip />
+ <string name="delete_notification_title" msgid="3329403967712437496">"ფაილების წაშლა…"</string>
<string name="copy_remaining" msgid="6283790937387975095">"დარჩა <xliff:g id="DURATION">%s</xliff:g>"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="other">მიმდინარეობს <xliff:g id="COUNT_1">%1$d</xliff:g> ფაილის კოპირება.</item>
@@ -113,7 +112,9 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"ზოგიერთი ფაილი გარდაქმნილია"</string>
<string name="allow" msgid="7225948811296386551">"უფლების მიცემა"</string>
<string name="deny" msgid="2081879885755434506">"აკრძალვა"</string>
- <!-- no translation found for delete_confirmation_title (1958369150786342998) -->
- <skip />
- <!-- no translation found for delete_confirmation_message (6608317554854868128) -->
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"გსურთ ფაილების წაშლა?"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="other">ნამდვილად გსურთ <xliff:g id="COUNT_1">%1$d</xliff:g> ფაილის წაშლა?</item>
+ <item quantity="one">ნამდვილად გსურთ <xliff:g id="COUNT_0">%1$d</xliff:g> ფაილის წაშლა?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-kk-rKZ/strings.xml b/packages/DocumentsUI/res/values-kk-rKZ/strings.xml
index ab045c6..ad10920 100644
--- a/packages/DocumentsUI/res/values-kk-rKZ/strings.xml
+++ b/packages/DocumentsUI/res/values-kk-rKZ/strings.xml
@@ -67,8 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"Бөлісу"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"Файлдарды көшіру"</string>
<string name="move_notification_title" msgid="6193835179777284805">"Файлдар тасымалдануда"</string>
- <!-- no translation found for delete_notification_title (3329403967712437496) -->
- <skip />
+ <string name="delete_notification_title" msgid="3329403967712437496">"Файлдар жойылуда"</string>
<string name="copy_remaining" msgid="6283790937387975095">"<xliff:g id="DURATION">%s</xliff:g> қалды"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> файлды көшіру.</item>
@@ -113,7 +112,9 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Кейбір файлдар түрлендірілді"</string>
<string name="allow" msgid="7225948811296386551">"Рұқсат беру"</string>
<string name="deny" msgid="2081879885755434506">"Бас тарту"</string>
- <!-- no translation found for delete_confirmation_title (1958369150786342998) -->
- <skip />
- <!-- no translation found for delete_confirmation_message (6608317554854868128) -->
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"Файлдарды жою керек пе?"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> файлды жою керек пе?</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> файлды жою керек пе?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-ky-rKG/strings.xml b/packages/DocumentsUI/res/values-ky-rKG/strings.xml
index ba3a6e3..134b5b8 100644
--- a/packages/DocumentsUI/res/values-ky-rKG/strings.xml
+++ b/packages/DocumentsUI/res/values-ky-rKG/strings.xml
@@ -67,8 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"Кийинки аркылуу бөлүшүү:"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"Файлдар көчүрүлүүдө"</string>
<string name="move_notification_title" msgid="6193835179777284805">"Файлдар жылдырылууда…"</string>
- <!-- no translation found for delete_notification_title (3329403967712437496) -->
- <skip />
+ <string name="delete_notification_title" msgid="3329403967712437496">"Файлдар жок кылынууда"</string>
<string name="copy_remaining" msgid="6283790937387975095">"<xliff:g id="DURATION">%s</xliff:g> калды"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> файл көчүрүлүүдө.</item>
@@ -113,7 +112,9 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Айрым файлдардын форматы өзгөртүлдү"</string>
<string name="allow" msgid="7225948811296386551">"Уруксат берүү"</string>
<string name="deny" msgid="2081879885755434506">"Жок"</string>
- <!-- no translation found for delete_confirmation_title (1958369150786342998) -->
- <skip />
- <!-- no translation found for delete_confirmation_message (6608317554854868128) -->
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"Файлдар жок кылынсынбы?"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="other">Бул <xliff:g id="COUNT_1">%1$d</xliff:g> файлды чын эле жок кылгыңыз келеби?</item>
+ <item quantity="one">Бул <xliff:g id="COUNT_0">%1$d</xliff:g> файлды чын эле жок кылгыңыз келеби?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-lt/strings.xml b/packages/DocumentsUI/res/values-lt/strings.xml
index 7e42922..194e5900 100644
--- a/packages/DocumentsUI/res/values-lt/strings.xml
+++ b/packages/DocumentsUI/res/values-lt/strings.xml
@@ -67,8 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"Bendrinti naudojant"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"Kopijuojami failai"</string>
<string name="move_notification_title" msgid="6193835179777284805">"Perkeliami failai"</string>
- <!-- no translation found for delete_notification_title (3329403967712437496) -->
- <skip />
+ <string name="delete_notification_title" msgid="3329403967712437496">"Failų ištrynimas"</string>
<string name="copy_remaining" msgid="6283790937387975095">"Liko: <xliff:g id="DURATION">%s</xliff:g>"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="one">Kopijuojamas <xliff:g id="COUNT_1">%1$d</xliff:g> failas.</item>
@@ -127,7 +126,11 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Kai kurie failai buvo konvertuoti"</string>
<string name="allow" msgid="7225948811296386551">"Leisti"</string>
<string name="deny" msgid="2081879885755434506">"Atmesti"</string>
- <!-- no translation found for delete_confirmation_title (1958369150786342998) -->
- <skip />
- <!-- no translation found for delete_confirmation_message (6608317554854868128) -->
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"Ištrinti failus?"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="one">]Ar tikrai norite ištrinti <xliff:g id="COUNT_1">%1$d</xliff:g> failą?</item>
+ <item quantity="few">]Ar tikrai norite ištrinti <xliff:g id="COUNT_1">%1$d</xliff:g> failus?</item>
+ <item quantity="many">]Ar tikrai norite ištrinti <xliff:g id="COUNT_1">%1$d</xliff:g> failo?</item>
+ <item quantity="other">]Ar tikrai norite ištrinti <xliff:g id="COUNT_1">%1$d</xliff:g> failų?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-lv/strings.xml b/packages/DocumentsUI/res/values-lv/strings.xml
index 14bd7a8..cd4cb5e 100644
--- a/packages/DocumentsUI/res/values-lv/strings.xml
+++ b/packages/DocumentsUI/res/values-lv/strings.xml
@@ -67,8 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"Kopīgot, izmantojot"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"Notiek failu kopēšana"</string>
<string name="move_notification_title" msgid="6193835179777284805">"Failu pārvietošana"</string>
- <!-- no translation found for delete_notification_title (3329403967712437496) -->
- <skip />
+ <string name="delete_notification_title" msgid="3329403967712437496">"Notiek failu dzēšana"</string>
<string name="copy_remaining" msgid="6283790937387975095">"Atlikušais laiks: <xliff:g id="DURATION">%s</xliff:g>"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="zero">Notiek <xliff:g id="COUNT_1">%1$d</xliff:g> failu kopēšana.</item>
@@ -120,7 +119,10 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Daži faili tika pārveidoti."</string>
<string name="allow" msgid="7225948811296386551">"Atļaut"</string>
<string name="deny" msgid="2081879885755434506">"Noraidīt"</string>
- <!-- no translation found for delete_confirmation_title (1958369150786342998) -->
- <skip />
- <!-- no translation found for delete_confirmation_message (6608317554854868128) -->
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"Vai dzēst failus?"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="zero">Vai tiešām vēlaties dzēst <xliff:g id="COUNT_1">%1$d</xliff:g> failus?</item>
+ <item quantity="one">Vai tiešām vēlaties dzēst <xliff:g id="COUNT_1">%1$d</xliff:g> failu?</item>
+ <item quantity="other">Vai tiešām vēlaties dzēst <xliff:g id="COUNT_1">%1$d</xliff:g> failus?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-mn-rMN/strings.xml b/packages/DocumentsUI/res/values-mn-rMN/strings.xml
index 8531295..a2617f9 100644
--- a/packages/DocumentsUI/res/values-mn-rMN/strings.xml
+++ b/packages/DocumentsUI/res/values-mn-rMN/strings.xml
@@ -67,8 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"Дараахаар дамжуулан хуваалцах"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"Файлуудыг хуулж байна"</string>
<string name="move_notification_title" msgid="6193835179777284805">"Файлыг зөөвөрлөж байна"</string>
- <!-- no translation found for delete_notification_title (3329403967712437496) -->
- <skip />
+ <string name="delete_notification_title" msgid="3329403967712437496">"Эдгээр файлыг устгаж байна"</string>
<string name="copy_remaining" msgid="6283790937387975095">"<xliff:g id="DURATION">%s</xliff:g> үлдсэн"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="other"> <xliff:g id="COUNT_1">%1$d</xliff:g> файлуудыг хуулж байна.</item>
@@ -113,7 +112,9 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Зарим файлыг хөрвүүлсэн"</string>
<string name="allow" msgid="7225948811296386551">"Зөвшөөрөх"</string>
<string name="deny" msgid="2081879885755434506">"Татгалзах"</string>
- <!-- no translation found for delete_confirmation_title (1958369150786342998) -->
- <skip />
- <!-- no translation found for delete_confirmation_message (6608317554854868128) -->
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"Эдгээр файлыг устгах уу?"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="other">Та <xliff:g id="COUNT_1">%1$d</xliff:g> файлыг устгахдаа итгэлтэй байна уу?</item>
+ <item quantity="one">Та <xliff:g id="COUNT_0">%1$d</xliff:g> файлыг устгахдаа итгэлтэй байна уу?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-mr-rIN/strings.xml b/packages/DocumentsUI/res/values-mr-rIN/strings.xml
index f747d1a..c44b481 100644
--- a/packages/DocumentsUI/res/values-mr-rIN/strings.xml
+++ b/packages/DocumentsUI/res/values-mr-rIN/strings.xml
@@ -67,8 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"द्वारे सामायिक करा"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"फायली कॉपी करीत आहे"</string>
<string name="move_notification_title" msgid="6193835179777284805">"फायली हलविणे"</string>
- <!-- no translation found for delete_notification_title (3329403967712437496) -->
- <skip />
+ <string name="delete_notification_title" msgid="3329403967712437496">"फायली हटवित आहे"</string>
<string name="copy_remaining" msgid="6283790937387975095">"<xliff:g id="DURATION">%s</xliff:g> शिल्लक"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> फाईल कॉपी करीत आहे.</item>
@@ -113,7 +112,9 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"काही फायली रूपांतरित केल्या होत्या"</string>
<string name="allow" msgid="7225948811296386551">"अनुमती द्या"</string>
<string name="deny" msgid="2081879885755434506">"नकार द्या"</string>
- <!-- no translation found for delete_confirmation_title (1958369150786342998) -->
- <skip />
- <!-- no translation found for delete_confirmation_message (6608317554854868128) -->
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"फायली हटवायच्या?"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="one">आपल्याला खात्री आहे की आपण <xliff:g id="COUNT_1">%1$d</xliff:g> फाईल हटवू इच्छिता?</item>
+ <item quantity="other">आपल्याला खात्री आहे की आपण <xliff:g id="COUNT_1">%1$d</xliff:g> फायली हटवू इच्छिता?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-ms-rMY/strings.xml b/packages/DocumentsUI/res/values-ms-rMY/strings.xml
index d481125..17cd348 100644
--- a/packages/DocumentsUI/res/values-ms-rMY/strings.xml
+++ b/packages/DocumentsUI/res/values-ms-rMY/strings.xml
@@ -67,8 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"Kongsi melalui"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"Menyalin fail"</string>
<string name="move_notification_title" msgid="6193835179777284805">"Mengalihkan fail"</string>
- <!-- no translation found for delete_notification_title (3329403967712437496) -->
- <skip />
+ <string name="delete_notification_title" msgid="3329403967712437496">"Memadamkan fail"</string>
<string name="copy_remaining" msgid="6283790937387975095">"<xliff:g id="DURATION">%s</xliff:g> lagi"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="other">Menyalin <xliff:g id="COUNT_1">%1$d</xliff:g> fail.</item>
@@ -113,7 +112,9 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Sesetengah fail telah ditukarkan"</string>
<string name="allow" msgid="7225948811296386551">"Benarkan"</string>
<string name="deny" msgid="2081879885755434506">"Nafi"</string>
- <!-- no translation found for delete_confirmation_title (1958369150786342998) -->
- <skip />
- <!-- no translation found for delete_confirmation_message (6608317554854868128) -->
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"Padamkan fail?"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="other">Adakah anda pasti mahu memadamkan <xliff:g id="COUNT_1">%1$d</xliff:g> fail?</item>
+ <item quantity="one">Adakah anda pasti mahu memadamkan <xliff:g id="COUNT_0">%1$d</xliff:g> fail?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-nb/strings.xml b/packages/DocumentsUI/res/values-nb/strings.xml
index 8271428..d42c98e 100644
--- a/packages/DocumentsUI/res/values-nb/strings.xml
+++ b/packages/DocumentsUI/res/values-nb/strings.xml
@@ -67,8 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"Del via"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"Kopierer filer"</string>
<string name="move_notification_title" msgid="6193835179777284805">"Flytter filer"</string>
- <!-- no translation found for delete_notification_title (3329403967712437496) -->
- <skip />
+ <string name="delete_notification_title" msgid="3329403967712437496">"Sletter filene"</string>
<string name="copy_remaining" msgid="6283790937387975095">"<xliff:g id="DURATION">%s</xliff:g> gjenstår"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="other">Kopierer <xliff:g id="COUNT_1">%1$d</xliff:g> filer.</item>
@@ -113,7 +112,9 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Noen filer er konvertert"</string>
<string name="allow" msgid="7225948811296386551">"Tillat"</string>
<string name="deny" msgid="2081879885755434506">"Avslå"</string>
- <!-- no translation found for delete_confirmation_title (1958369150786342998) -->
- <skip />
- <!-- no translation found for delete_confirmation_message (6608317554854868128) -->
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"Vil du slette filene?"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="other">Er du sikker på at du vil slette <xliff:g id="COUNT_1">%1$d</xliff:g> filer?</item>
+ <item quantity="one">Er du sikker på at du vil slette <xliff:g id="COUNT_0">%1$d</xliff:g> fil?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-pl/strings.xml b/packages/DocumentsUI/res/values-pl/strings.xml
index 7330e1e..d334194 100644
--- a/packages/DocumentsUI/res/values-pl/strings.xml
+++ b/packages/DocumentsUI/res/values-pl/strings.xml
@@ -67,8 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"Udostępnij przez:"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"Kopiowanie plików"</string>
<string name="move_notification_title" msgid="6193835179777284805">"Przenoszenie plików"</string>
- <!-- no translation found for delete_notification_title (3329403967712437496) -->
- <skip />
+ <string name="delete_notification_title" msgid="3329403967712437496">"Usuwam pliki"</string>
<string name="copy_remaining" msgid="6283790937387975095">"Pozostało: <xliff:g id="DURATION">%s</xliff:g>"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="few">Kopiowanie <xliff:g id="COUNT_1">%1$d</xliff:g> plików.</item>
@@ -127,7 +126,11 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Niektóre pliki zostały przekonwertowane"</string>
<string name="allow" msgid="7225948811296386551">"Zezwól"</string>
<string name="deny" msgid="2081879885755434506">"Odmów"</string>
- <!-- no translation found for delete_confirmation_title (1958369150786342998) -->
- <skip />
- <!-- no translation found for delete_confirmation_message (6608317554854868128) -->
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"Usunąć pliki?"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="few">Na pewno chcesz usunąć <xliff:g id="COUNT_1">%1$d</xliff:g> pliki?</item>
+ <item quantity="many">Na pewno chcesz usunąć <xliff:g id="COUNT_1">%1$d</xliff:g> plików?</item>
+ <item quantity="other">Na pewno chcesz usunąć <xliff:g id="COUNT_1">%1$d</xliff:g> pliku?</item>
+ <item quantity="one">Na pewno chcesz usunąć <xliff:g id="COUNT_0">%1$d</xliff:g> plik?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-pt-rBR/strings.xml b/packages/DocumentsUI/res/values-pt-rBR/strings.xml
index 44f2ab8..cc55006 100644
--- a/packages/DocumentsUI/res/values-pt-rBR/strings.xml
+++ b/packages/DocumentsUI/res/values-pt-rBR/strings.xml
@@ -67,8 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"Compartilhar via"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"Copiando arquivos"</string>
<string name="move_notification_title" msgid="6193835179777284805">"Movendo arquivos"</string>
- <!-- no translation found for delete_notification_title (3329403967712437496) -->
- <skip />
+ <string name="delete_notification_title" msgid="3329403967712437496">"Excluindo arquivos"</string>
<string name="copy_remaining" msgid="6283790937387975095">"<xliff:g id="DURATION">%s</xliff:g> restantes"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="one">Copiando <xliff:g id="COUNT_1">%1$d</xliff:g> arquivos.</item>
@@ -113,7 +112,9 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Alguns arquivos foram convertidos"</string>
<string name="allow" msgid="7225948811296386551">"Permitir"</string>
<string name="deny" msgid="2081879885755434506">"Negar"</string>
- <!-- no translation found for delete_confirmation_title (1958369150786342998) -->
- <skip />
- <!-- no translation found for delete_confirmation_message (6608317554854868128) -->
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"Excluir arquivos?"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="one">Tem certeza de que deseja excluir <xliff:g id="COUNT_1">%1$d</xliff:g> arquivos?</item>
+ <item quantity="other">Tem certeza de que deseja excluir <xliff:g id="COUNT_1">%1$d</xliff:g> arquivos?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-pt-rPT/strings.xml b/packages/DocumentsUI/res/values-pt-rPT/strings.xml
index 3d999c7..1e51019 100644
--- a/packages/DocumentsUI/res/values-pt-rPT/strings.xml
+++ b/packages/DocumentsUI/res/values-pt-rPT/strings.xml
@@ -67,8 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"Partilhar através de"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"A copiar ficheiros"</string>
<string name="move_notification_title" msgid="6193835179777284805">"A mover ficheiros"</string>
- <!-- no translation found for delete_notification_title (3329403967712437496) -->
- <skip />
+ <string name="delete_notification_title" msgid="3329403967712437496">"Eliminar ficheiros"</string>
<string name="copy_remaining" msgid="6283790937387975095">"Faltam <xliff:g id="DURATION">%s</xliff:g>"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="other">A copiar <xliff:g id="COUNT_1">%1$d</xliff:g> ficheiros.</item>
@@ -113,7 +112,9 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Alguns ficheiros foram convertidos"</string>
<string name="allow" msgid="7225948811296386551">"Permitir"</string>
<string name="deny" msgid="2081879885755434506">"Recusar"</string>
- <!-- no translation found for delete_confirmation_title (1958369150786342998) -->
- <skip />
- <!-- no translation found for delete_confirmation_message (6608317554854868128) -->
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"Pretende eliminar ficheiros?"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="other">Tem a certeza de que pretende eliminar <xliff:g id="COUNT_1">%1$d</xliff:g> ficheiros?</item>
+ <item quantity="one">Tem a certeza de que pretende eliminar <xliff:g id="COUNT_0">%1$d</xliff:g> ficheiro?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-pt/strings.xml b/packages/DocumentsUI/res/values-pt/strings.xml
index 44f2ab8..cc55006 100644
--- a/packages/DocumentsUI/res/values-pt/strings.xml
+++ b/packages/DocumentsUI/res/values-pt/strings.xml
@@ -67,8 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"Compartilhar via"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"Copiando arquivos"</string>
<string name="move_notification_title" msgid="6193835179777284805">"Movendo arquivos"</string>
- <!-- no translation found for delete_notification_title (3329403967712437496) -->
- <skip />
+ <string name="delete_notification_title" msgid="3329403967712437496">"Excluindo arquivos"</string>
<string name="copy_remaining" msgid="6283790937387975095">"<xliff:g id="DURATION">%s</xliff:g> restantes"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="one">Copiando <xliff:g id="COUNT_1">%1$d</xliff:g> arquivos.</item>
@@ -113,7 +112,9 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Alguns arquivos foram convertidos"</string>
<string name="allow" msgid="7225948811296386551">"Permitir"</string>
<string name="deny" msgid="2081879885755434506">"Negar"</string>
- <!-- no translation found for delete_confirmation_title (1958369150786342998) -->
- <skip />
- <!-- no translation found for delete_confirmation_message (6608317554854868128) -->
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"Excluir arquivos?"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="one">Tem certeza de que deseja excluir <xliff:g id="COUNT_1">%1$d</xliff:g> arquivos?</item>
+ <item quantity="other">Tem certeza de que deseja excluir <xliff:g id="COUNT_1">%1$d</xliff:g> arquivos?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-ro/strings.xml b/packages/DocumentsUI/res/values-ro/strings.xml
index d256a26..9932bd8 100644
--- a/packages/DocumentsUI/res/values-ro/strings.xml
+++ b/packages/DocumentsUI/res/values-ro/strings.xml
@@ -67,8 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"Trimiteți prin"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"Se copiază fișierele"</string>
<string name="move_notification_title" msgid="6193835179777284805">"Se mută fișierele"</string>
- <!-- no translation found for delete_notification_title (3329403967712437496) -->
- <skip />
+ <string name="delete_notification_title" msgid="3329403967712437496">"Se șterg fișierele"</string>
<string name="copy_remaining" msgid="6283790937387975095">"Timp rămas: <xliff:g id="DURATION">%s</xliff:g>"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="few">Se copiază <xliff:g id="COUNT_1">%1$d</xliff:g> fișiere.</item>
@@ -120,7 +119,10 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Unele fișiere au fost convertite"</string>
<string name="allow" msgid="7225948811296386551">"Permiteți"</string>
<string name="deny" msgid="2081879885755434506">"Refuzați"</string>
- <!-- no translation found for delete_confirmation_title (1958369150786342998) -->
- <skip />
- <!-- no translation found for delete_confirmation_message (6608317554854868128) -->
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"Ștergeți fișierele?"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="few">Sigur doriți să ștergeți <xliff:g id="COUNT_1">%1$d</xliff:g> fișiere?</item>
+ <item quantity="other">Sigur doriți să ștergeți <xliff:g id="COUNT_1">%1$d</xliff:g> de fișiere?</item>
+ <item quantity="one">Sigur doriți să ștergeți <xliff:g id="COUNT_0">%1$d</xliff:g> fișier?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-ru/strings.xml b/packages/DocumentsUI/res/values-ru/strings.xml
index 161bb19..ebddb27 100644
--- a/packages/DocumentsUI/res/values-ru/strings.xml
+++ b/packages/DocumentsUI/res/values-ru/strings.xml
@@ -67,8 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"Поделиться"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"Копирование файлов"</string>
<string name="move_notification_title" msgid="6193835179777284805">"Перемещение файлов"</string>
- <!-- no translation found for delete_notification_title (3329403967712437496) -->
- <skip />
+ <string name="delete_notification_title" msgid="3329403967712437496">"Удаление файлов…"</string>
<string name="copy_remaining" msgid="6283790937387975095">"Осталось <xliff:g id="DURATION">%s</xliff:g>"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="one">Копируется <xliff:g id="COUNT_1">%1$d</xliff:g> файл...</item>
@@ -127,7 +126,11 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Формат некоторых файлов изменен"</string>
<string name="allow" msgid="7225948811296386551">"Разрешить"</string>
<string name="deny" msgid="2081879885755434506">"Отклонить"</string>
- <!-- no translation found for delete_confirmation_title (1958369150786342998) -->
- <skip />
- <!-- no translation found for delete_confirmation_message (6608317554854868128) -->
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"Удаление файлов"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="one">Удалить <xliff:g id="COUNT_1">%1$d</xliff:g> файл?</item>
+ <item quantity="few">Удалить <xliff:g id="COUNT_1">%1$d</xliff:g> файла?</item>
+ <item quantity="many">Удалить <xliff:g id="COUNT_1">%1$d</xliff:g> файлов?</item>
+ <item quantity="other">Удалить <xliff:g id="COUNT_1">%1$d</xliff:g> файла?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-sk/strings.xml b/packages/DocumentsUI/res/values-sk/strings.xml
index 7919533..7b3c213 100644
--- a/packages/DocumentsUI/res/values-sk/strings.xml
+++ b/packages/DocumentsUI/res/values-sk/strings.xml
@@ -67,8 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"Zdieľať"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"Kopírovanie súborov"</string>
<string name="move_notification_title" msgid="6193835179777284805">"Presúvajú sa súbory"</string>
- <!-- no translation found for delete_notification_title (3329403967712437496) -->
- <skip />
+ <string name="delete_notification_title" msgid="3329403967712437496">"Odstraňujú sa súbory"</string>
<string name="copy_remaining" msgid="6283790937387975095">"Zostáva: <xliff:g id="DURATION">%s</xliff:g>"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="few">Kopírujú sa <xliff:g id="COUNT_1">%1$d</xliff:g> súbory.</item>
@@ -127,7 +126,11 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Niektoré súbory boli konvertované"</string>
<string name="allow" msgid="7225948811296386551">"Povoliť"</string>
<string name="deny" msgid="2081879885755434506">"Zamietnuť"</string>
- <!-- no translation found for delete_confirmation_title (1958369150786342998) -->
- <skip />
- <!-- no translation found for delete_confirmation_message (6608317554854868128) -->
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"Odstrániť súbory?"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="few">Naozaj chcete odstrániť <xliff:g id="COUNT_1">%1$d</xliff:g> súbory?</item>
+ <item quantity="many">Naozaj chcete odstrániť <xliff:g id="COUNT_1">%1$d</xliff:g> súboru?</item>
+ <item quantity="other">Naozaj chcete odstrániť <xliff:g id="COUNT_1">%1$d</xliff:g> súborov?</item>
+ <item quantity="one">Naozaj chcete odstrániť <xliff:g id="COUNT_0">%1$d</xliff:g> súbor?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-sr/strings.xml b/packages/DocumentsUI/res/values-sr/strings.xml
index ffa6944..7575ff8 100644
--- a/packages/DocumentsUI/res/values-sr/strings.xml
+++ b/packages/DocumentsUI/res/values-sr/strings.xml
@@ -67,8 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"Делите преко"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"Копирање датотека"</string>
<string name="move_notification_title" msgid="6193835179777284805">"Датотеке се премештају"</string>
- <!-- no translation found for delete_notification_title (3329403967712437496) -->
- <skip />
+ <string name="delete_notification_title" msgid="3329403967712437496">"Датотеке се бришу"</string>
<string name="copy_remaining" msgid="6283790937387975095">"Још <xliff:g id="DURATION">%s</xliff:g>"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="one">Копирање <xliff:g id="COUNT_1">%1$d</xliff:g> датотеке.</item>
@@ -120,7 +119,10 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Неке датотеке су конвертоване"</string>
<string name="allow" msgid="7225948811296386551">"Дозволи"</string>
<string name="deny" msgid="2081879885755434506">"Одбиј"</string>
- <!-- no translation found for delete_confirmation_title (1958369150786342998) -->
- <skip />
- <!-- no translation found for delete_confirmation_message (6608317554854868128) -->
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"Желите ли да избришете датотеке?"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="one">Желите ли стварно да избришете <xliff:g id="COUNT_1">%1$d</xliff:g> датотеку?</item>
+ <item quantity="few">Желите ли стварно да избришете <xliff:g id="COUNT_1">%1$d</xliff:g> датотеке?</item>
+ <item quantity="other">Желите ли стварно да избришете <xliff:g id="COUNT_1">%1$d</xliff:g> датотека?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-sv/strings.xml b/packages/DocumentsUI/res/values-sv/strings.xml
index 656ef8f..97e6ab0 100644
--- a/packages/DocumentsUI/res/values-sv/strings.xml
+++ b/packages/DocumentsUI/res/values-sv/strings.xml
@@ -67,8 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"Dela via"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"Kopierar filer"</string>
<string name="move_notification_title" msgid="6193835179777284805">"Filer flyttas"</string>
- <!-- no translation found for delete_notification_title (3329403967712437496) -->
- <skip />
+ <string name="delete_notification_title" msgid="3329403967712437496">"Filerna tas bort"</string>
<string name="copy_remaining" msgid="6283790937387975095">"<xliff:g id="DURATION">%s</xliff:g> återstår"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="other">Kopierar <xliff:g id="COUNT_1">%1$d</xliff:g> filer.</item>
@@ -113,7 +112,9 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Vissa filer konverterades"</string>
<string name="allow" msgid="7225948811296386551">"Tillåt"</string>
<string name="deny" msgid="2081879885755434506">"Neka"</string>
- <!-- no translation found for delete_confirmation_title (1958369150786342998) -->
- <skip />
- <!-- no translation found for delete_confirmation_message (6608317554854868128) -->
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"Vill du ta bort filerna?"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="other">Vill du ta bort <xliff:g id="COUNT_1">%1$d</xliff:g> filer?</item>
+ <item quantity="one">Vill du ta bort <xliff:g id="COUNT_0">%1$d</xliff:g> fil?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-sw720dp/dimens.xml b/packages/DocumentsUI/res/values-sw720dp/dimens.xml
index 2488fa2..b5d1150 100644
--- a/packages/DocumentsUI/res/values-sw720dp/dimens.xml
+++ b/packages/DocumentsUI/res/values-sw720dp/dimens.xml
@@ -18,4 +18,6 @@
<dimen name="grid_padding_horiz">16dp</dimen>
<dimen name="grid_padding_vert">16dp</dimen>
+ <dimen name="list_item_padding">24dp</dimen>
+
</resources>
diff --git a/packages/DocumentsUI/res/values-th/strings.xml b/packages/DocumentsUI/res/values-th/strings.xml
index ad4c5b9..8881fcd 100644
--- a/packages/DocumentsUI/res/values-th/strings.xml
+++ b/packages/DocumentsUI/res/values-th/strings.xml
@@ -67,8 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"แชร์ผ่าน"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"กำลังคัดลอกไฟล์"</string>
<string name="move_notification_title" msgid="6193835179777284805">"กำลังย้ายไฟล์"</string>
- <!-- no translation found for delete_notification_title (3329403967712437496) -->
- <skip />
+ <string name="delete_notification_title" msgid="3329403967712437496">"กำลังลบไฟล์"</string>
<string name="copy_remaining" msgid="6283790937387975095">"เหลือ <xliff:g id="DURATION">%s</xliff:g>"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="other">กำลังคัดลอก <xliff:g id="COUNT_1">%1$d</xliff:g> ไฟล์</item>
@@ -113,7 +112,9 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"แปลงบางไฟล์แล้ว"</string>
<string name="allow" msgid="7225948811296386551">"อนุญาต"</string>
<string name="deny" msgid="2081879885755434506">"ปฏิเสธ"</string>
- <!-- no translation found for delete_confirmation_title (1958369150786342998) -->
- <skip />
- <!-- no translation found for delete_confirmation_message (6608317554854868128) -->
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"ลบไฟล์เหล่านี้ไหม"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="other">คุณแน่ใจไหมว่าต้องการลบ <xliff:g id="COUNT_1">%1$d</xliff:g> ไฟล์</item>
+ <item quantity="one">คุณแน่ใจไหมว่าต้องการลบ <xliff:g id="COUNT_0">%1$d</xliff:g> ไฟล์</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-tl/strings.xml b/packages/DocumentsUI/res/values-tl/strings.xml
index 8c8b018..1639425 100644
--- a/packages/DocumentsUI/res/values-tl/strings.xml
+++ b/packages/DocumentsUI/res/values-tl/strings.xml
@@ -67,8 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"Ibahagi sa pamamagitan ng"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"Kinokopya ang mga file"</string>
<string name="move_notification_title" msgid="6193835179777284805">"Inililipat ang mga file"</string>
- <!-- no translation found for delete_notification_title (3329403967712437496) -->
- <skip />
+ <string name="delete_notification_title" msgid="3329403967712437496">"Pagde-delete ng mga file"</string>
<string name="copy_remaining" msgid="6283790937387975095">"<xliff:g id="DURATION">%s</xliff:g> na lang ang natitira"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="one">Kumokopya ng <xliff:g id="COUNT_1">%1$d</xliff:g> file.</item>
@@ -113,7 +112,9 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Na-convert ang ilang file"</string>
<string name="allow" msgid="7225948811296386551">"Payagan"</string>
<string name="deny" msgid="2081879885755434506">"Tanggihan"</string>
- <!-- no translation found for delete_confirmation_title (1958369150786342998) -->
- <skip />
- <!-- no translation found for delete_confirmation_message (6608317554854868128) -->
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"I-delete ang mga file?"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="one">Sigurado ka bang gusto mong i-delete ang <xliff:g id="COUNT_1">%1$d</xliff:g> file?</item>
+ <item quantity="other">Sigurado ka bang gusto mong i-delete ang <xliff:g id="COUNT_1">%1$d</xliff:g> na file?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-tr/strings.xml b/packages/DocumentsUI/res/values-tr/strings.xml
index 602f8d7..822a9ed 100644
--- a/packages/DocumentsUI/res/values-tr/strings.xml
+++ b/packages/DocumentsUI/res/values-tr/strings.xml
@@ -67,8 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"Şunu kullanarak paylaş:"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"Dosyalar kopyalanıyor"</string>
<string name="move_notification_title" msgid="6193835179777284805">"Dosyalar taşınıyor"</string>
- <!-- no translation found for delete_notification_title (3329403967712437496) -->
- <skip />
+ <string name="delete_notification_title" msgid="3329403967712437496">"Dosyalar siliniyor"</string>
<string name="copy_remaining" msgid="6283790937387975095">"<xliff:g id="DURATION">%s</xliff:g> kaldı"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> dosya kopyalanıyor.</item>
@@ -113,7 +112,9 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Bazı dosyalar dönüştürüldü"</string>
<string name="allow" msgid="7225948811296386551">"İzin Ver"</string>
<string name="deny" msgid="2081879885755434506">"Reddet"</string>
- <!-- no translation found for delete_confirmation_title (1958369150786342998) -->
- <skip />
- <!-- no translation found for delete_confirmation_message (6608317554854868128) -->
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"Dosyalar silinsin mi?"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> dosyayı silmek istediğinizden emin misiniz?</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> dosyayı silmek istediğinizden emin misiniz?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-uk/strings.xml b/packages/DocumentsUI/res/values-uk/strings.xml
index 15ae424..1886ca3 100644
--- a/packages/DocumentsUI/res/values-uk/strings.xml
+++ b/packages/DocumentsUI/res/values-uk/strings.xml
@@ -67,8 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"Надіслати через"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"Копіювання файлів"</string>
<string name="move_notification_title" msgid="6193835179777284805">"Переміщення файлів"</string>
- <!-- no translation found for delete_notification_title (3329403967712437496) -->
- <skip />
+ <string name="delete_notification_title" msgid="3329403967712437496">"Видалення файлів"</string>
<string name="copy_remaining" msgid="6283790937387975095">"Залишилося <xliff:g id="DURATION">%s</xliff:g>"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="one">Копіювання <xliff:g id="COUNT_1">%1$d</xliff:g> файлу.</item>
@@ -127,7 +126,11 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Деякі файли конвертовано"</string>
<string name="allow" msgid="7225948811296386551">"Дозвол."</string>
<string name="deny" msgid="2081879885755434506">"Забор."</string>
- <!-- no translation found for delete_confirmation_title (1958369150786342998) -->
- <skip />
- <!-- no translation found for delete_confirmation_message (6608317554854868128) -->
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"Видалити файли?"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="one">Видалити <xliff:g id="COUNT_1">%1$d</xliff:g> файл?</item>
+ <item quantity="few">Видалити <xliff:g id="COUNT_1">%1$d</xliff:g> файли?</item>
+ <item quantity="many">Видалити <xliff:g id="COUNT_1">%1$d</xliff:g> файлів?</item>
+ <item quantity="other">Видалити <xliff:g id="COUNT_1">%1$d</xliff:g> файлу?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-ur-rPK/strings.xml b/packages/DocumentsUI/res/values-ur-rPK/strings.xml
index 272677f..82d20e3 100644
--- a/packages/DocumentsUI/res/values-ur-rPK/strings.xml
+++ b/packages/DocumentsUI/res/values-ur-rPK/strings.xml
@@ -67,8 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"اشتراک کریں بذریعہ"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"فائلیں کاپی ہو رہی ہیں"</string>
<string name="move_notification_title" msgid="6193835179777284805">"فائلیں منتقل ہو رہی ہیں"</string>
- <!-- no translation found for delete_notification_title (3329403967712437496) -->
- <skip />
+ <string name="delete_notification_title" msgid="3329403967712437496">"فائلیں حذف کی جا رہی ہیں"</string>
<string name="copy_remaining" msgid="6283790937387975095">"<xliff:g id="DURATION">%s</xliff:g> باقی ہے"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> فائلیں کاپی کی جا رہی ہیں۔</item>
@@ -113,7 +112,9 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"کچھ فائلوں کو تبدیل کیا گیا تھا"</string>
<string name="allow" msgid="7225948811296386551">"اجازت دیں"</string>
<string name="deny" msgid="2081879885755434506">"مسترد کریں"</string>
- <!-- no translation found for delete_confirmation_title (1958369150786342998) -->
- <skip />
- <!-- no translation found for delete_confirmation_message (6608317554854868128) -->
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"فائلوں کو حذف کریں؟"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="other">کیا آپ واقعی <xliff:g id="COUNT_1">%1$d</xliff:g> فائلیں حذف کرنا چاہتے ہیں؟</item>
+ <item quantity="one">کیا آپ واقعی <xliff:g id="COUNT_0">%1$d</xliff:g> فائل حذف کرنا چاہتے ہیں؟</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-uz-rUZ/strings.xml b/packages/DocumentsUI/res/values-uz-rUZ/strings.xml
index 0a599c5..ce43fc2 100644
--- a/packages/DocumentsUI/res/values-uz-rUZ/strings.xml
+++ b/packages/DocumentsUI/res/values-uz-rUZ/strings.xml
@@ -67,8 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"Quyidagi orqali ulashish"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"Fayllar nusxalanmoqda"</string>
<string name="move_notification_title" msgid="6193835179777284805">"Ko‘chirib o‘tkazilmoqda"</string>
- <!-- no translation found for delete_notification_title (3329403967712437496) -->
- <skip />
+ <string name="delete_notification_title" msgid="3329403967712437496">"Fayllar o‘chirilmoqda"</string>
<string name="copy_remaining" msgid="6283790937387975095">"<xliff:g id="DURATION">%s</xliff:g> qoldi"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="other"> <xliff:g id="COUNT_1">%1$d</xliff:g> ta fayl nusxalanmoqda</item>
@@ -113,7 +112,9 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Bir nechta fayllar o‘girildi"</string>
<string name="allow" msgid="7225948811296386551">"Ruxsat berish"</string>
<string name="deny" msgid="2081879885755434506">"Rad qilish"</string>
- <!-- no translation found for delete_confirmation_title (1958369150786342998) -->
- <skip />
- <!-- no translation found for delete_confirmation_message (6608317554854868128) -->
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"Fayllar o‘chirib tashlansinmi?"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> ta fayl o‘chirib tashlansinmi?</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> ta fayl o‘chirib tashlansinmi?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-zh-rCN/strings.xml b/packages/DocumentsUI/res/values-zh-rCN/strings.xml
index 83a9204..6e87c81 100644
--- a/packages/DocumentsUI/res/values-zh-rCN/strings.xml
+++ b/packages/DocumentsUI/res/values-zh-rCN/strings.xml
@@ -67,8 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"分享方式"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"正在复制文件"</string>
<string name="move_notification_title" msgid="6193835179777284805">"正在移动文件"</string>
- <!-- no translation found for delete_notification_title (3329403967712437496) -->
- <skip />
+ <string name="delete_notification_title" msgid="3329403967712437496">"正在删除文件"</string>
<string name="copy_remaining" msgid="6283790937387975095">"剩余时间:<xliff:g id="DURATION">%s</xliff:g>"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="other">正在复制 <xliff:g id="COUNT_1">%1$d</xliff:g> 个文件。</item>
@@ -113,7 +112,9 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"部分文件已转换成其他格式"</string>
<string name="allow" msgid="7225948811296386551">"允许"</string>
<string name="deny" msgid="2081879885755434506">"拒绝"</string>
- <!-- no translation found for delete_confirmation_title (1958369150786342998) -->
- <skip />
- <!-- no translation found for delete_confirmation_message (6608317554854868128) -->
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"要删除文件吗?"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="other">您确定要删除 <xliff:g id="COUNT_1">%1$d</xliff:g> 个文件吗?</item>
+ <item quantity="one">您确定要删除 <xliff:g id="COUNT_0">%1$d</xliff:g> 个文件吗?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-zh-rHK/strings.xml b/packages/DocumentsUI/res/values-zh-rHK/strings.xml
index 532f976..345bba4 100644
--- a/packages/DocumentsUI/res/values-zh-rHK/strings.xml
+++ b/packages/DocumentsUI/res/values-zh-rHK/strings.xml
@@ -67,8 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"分享方式:"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"正在複製檔案"</string>
<string name="move_notification_title" msgid="6193835179777284805">"正在移動檔案"</string>
- <!-- no translation found for delete_notification_title (3329403967712437496) -->
- <skip />
+ <string name="delete_notification_title" msgid="3329403967712437496">"正在刪除檔案"</string>
<string name="copy_remaining" msgid="6283790937387975095">"剩餘 <xliff:g id="DURATION">%s</xliff:g>"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="other">正在複製 <xliff:g id="COUNT_1">%1$d</xliff:g> 個檔案。</item>
@@ -113,7 +112,9 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"部分檔案已轉換成其他格式"</string>
<string name="allow" msgid="7225948811296386551">"允許"</string>
<string name="deny" msgid="2081879885755434506">"拒絕"</string>
- <!-- no translation found for delete_confirmation_title (1958369150786342998) -->
- <skip />
- <!-- no translation found for delete_confirmation_message (6608317554854868128) -->
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"要刪除檔案嗎?"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="other">您確定要刪除 <xliff:g id="COUNT_1">%1$d</xliff:g> 個檔案嗎?</item>
+ <item quantity="one">您確定要刪除 <xliff:g id="COUNT_0">%1$d</xliff:g> 個檔案嗎?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-zh-rTW/strings.xml b/packages/DocumentsUI/res/values-zh-rTW/strings.xml
index e8b48cc..c799fb3 100644
--- a/packages/DocumentsUI/res/values-zh-rTW/strings.xml
+++ b/packages/DocumentsUI/res/values-zh-rTW/strings.xml
@@ -67,8 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"分享方式:"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"複製檔案"</string>
<string name="move_notification_title" msgid="6193835179777284805">"正在移動檔案"</string>
- <!-- no translation found for delete_notification_title (3329403967712437496) -->
- <skip />
+ <string name="delete_notification_title" msgid="3329403967712437496">"正在刪除檔案"</string>
<string name="copy_remaining" msgid="6283790937387975095">"剩餘 <xliff:g id="DURATION">%s</xliff:g>"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="other">正在複製 <xliff:g id="COUNT_1">%1$d</xliff:g> 個檔案。</item>
@@ -113,7 +112,9 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"部分檔案已轉換成其他格式"</string>
<string name="allow" msgid="7225948811296386551">"允許"</string>
<string name="deny" msgid="2081879885755434506">"拒絕"</string>
- <!-- no translation found for delete_confirmation_title (1958369150786342998) -->
- <skip />
- <!-- no translation found for delete_confirmation_message (6608317554854868128) -->
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"要刪除檔案嗎?"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="other">確定要刪除 <xliff:g id="COUNT_1">%1$d</xliff:g> 個檔案嗎?</item>
+ <item quantity="one">確定要刪除 <xliff:g id="COUNT_0">%1$d</xliff:g> 個檔案嗎?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values-zu/strings.xml b/packages/DocumentsUI/res/values-zu/strings.xml
index b22f994..eda4f7b 100644
--- a/packages/DocumentsUI/res/values-zu/strings.xml
+++ b/packages/DocumentsUI/res/values-zu/strings.xml
@@ -67,8 +67,7 @@
<string name="share_via" msgid="8966594246261344259">"Yabelana nge-"</string>
<string name="copy_notification_title" msgid="6374299806748219777">"Ikopisha amafayela"</string>
<string name="move_notification_title" msgid="6193835179777284805">"Ihambisa amafayela"</string>
- <!-- no translation found for delete_notification_title (3329403967712437496) -->
- <skip />
+ <string name="delete_notification_title" msgid="3329403967712437496">"Ukususa amafayela"</string>
<string name="copy_remaining" msgid="6283790937387975095">"<xliff:g id="DURATION">%s</xliff:g> okusele"</string>
<plurals name="copy_begin" formatted="false" msgid="9071199452634086365">
<item quantity="one">Ikopisha amafayela angu-<xliff:g id="COUNT_1">%1$d</xliff:g>.</item>
@@ -113,7 +112,9 @@
<string name="notification_copy_files_converted_title" msgid="3153573223054275181">"Amanye amafayela aguqulelwe"</string>
<string name="allow" msgid="7225948811296386551">"Vumela"</string>
<string name="deny" msgid="2081879885755434506">"Yala"</string>
- <!-- no translation found for delete_confirmation_title (1958369150786342998) -->
- <skip />
- <!-- no translation found for delete_confirmation_message (6608317554854868128) -->
+ <string name="delete_confirmation_title" msgid="1958369150786342998">"Susa amafayela?"</string>
+ <plurals name="delete_confirmation_message" formatted="false" msgid="6608317554854868128">
+ <item quantity="one">Ingabe uqinisekile ukuthi ufuna ukususa amafayela angu-<xliff:g id="COUNT_1">%1$d</xliff:g>?</item>
+ <item quantity="other">Ingabe uqinisekile ukuthi ufuna ukususa amafayela angu-<xliff:g id="COUNT_1">%1$d</xliff:g>?</item>
+ </plurals>
</resources>
diff --git a/packages/DocumentsUI/res/values/strings.xml b/packages/DocumentsUI/res/values/strings.xml
index 3dc111a..6e1b30e 100644
--- a/packages/DocumentsUI/res/values/strings.xml
+++ b/packages/DocumentsUI/res/values/strings.xml
@@ -208,11 +208,9 @@
<string name="allow">Allow</string>
<!-- Text in the button asking user to deny access to a given directory. -->
<string name="deny">Deny</string>
- <!-- Dialog title shown to users when asking if they want to delete files (a confirmation). -->
- <string name="delete_confirmation_title">Delete files?</string>
<!-- Dialog text shown to users when asking if they want to delete files (a confirmation). -->
<plurals name="delete_confirmation_message">
- <item quantity="one">Are you sure you want to delete <xliff:g id="count" example="1">%1$d</xliff:g> file?</item>
- <item quantity="other">Are you sure you want to delete <xliff:g id="count" example="3">%1$d</xliff:g> files?</item>
+ <item quantity="one">Delete <xliff:g id="count" example="1">%1$d</xliff:g> file?</item>
+ <item quantity="other">Delete <xliff:g id="count" example="3">%1$d</xliff:g> files?</item>
</plurals>
</resources>
diff --git a/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java b/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java
index 46cbbdf..6efe9d1 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java
@@ -39,6 +39,7 @@
import android.support.annotation.CallSuper;
import android.support.annotation.LayoutRes;
import android.support.annotation.Nullable;
+import android.support.annotation.VisibleForTesting;
import android.util.Log;
import android.view.KeyEvent;
import android.view.Menu;
@@ -67,6 +68,7 @@
SearchViewManager mSearchManager;
DrawerController mDrawer;
NavigationView mNavigator;
+ List<EventListener> mEventListeners = new ArrayList<>();
private final String mTag;
@@ -149,7 +151,6 @@
final MenuItem sortSize = menu.findItem(R.id.menu_sort_size);
final MenuItem grid = menu.findItem(R.id.menu_grid);
final MenuItem list = menu.findItem(R.id.menu_list);
- final MenuItem advanced = menu.findItem(R.id.menu_advanced);
final MenuItem fileSize = menu.findItem(R.id.menu_file_size);
// Search uses backend ranking; no sorting, recents doesn't support sort.
@@ -161,9 +162,6 @@
grid.setVisible(mState.derivedMode != State.MODE_GRID);
list.setVisible(mState.derivedMode != State.MODE_LIST);
- advanced.setVisible(!mState.forceAdvanced);
- advanced.setTitle(LocalPreferences.getDisplayAdvancedDevices(this)
- ? R.string.menu_advanced_hide : R.string.menu_advanced_show);
fileSize.setTitle(LocalPreferences.getDisplayFileSize(this)
? R.string.menu_file_size_hide : R.string.menu_file_size_show);
@@ -199,10 +197,6 @@
state.forceSize = intent.getBooleanExtra(DocumentsContract.EXTRA_SHOW_FILESIZE, false);
state.showSize = state.forceSize || LocalPreferences.getDisplayFileSize(this);
- state.forceAdvanced = intent.getBooleanExtra(DocumentsContract.EXTRA_SHOW_ADVANCED, false);
- state.showAdvanced = state.forceAdvanced
- || LocalPreferences.getDisplayAdvancedDevices(this);
-
state.initAcceptMimes(intent);
state.excludedAuthorities = getExcludedAuthorities();
@@ -278,10 +272,6 @@
}
return true;
- case R.id.menu_advanced:
- setDisplayAdvancedDevices(!LocalPreferences.getDisplayAdvancedDevices(this));
- return true;
-
case R.id.menu_file_size:
setDisplayFileSize(!LocalPreferences.getDisplayFileSize(this));
return true;
@@ -329,6 +319,8 @@
void openContainerDocument(DocumentInfo doc) {
assert(doc.isContainer());
+ notifyDirectoryNavigated(doc.derivedUri);
+
mState.pushDocument(doc);
// Show an opening animation only if pressing "back" would get us back to the
// previous directory. Especially after opening a root document, pressing
@@ -431,13 +423,6 @@
return mState;
}
- void setDisplayAdvancedDevices(boolean display) {
- LocalPreferences.setDisplayAdvancedDevices(this, display);
- mState.showAdvanced = mState.forceAdvanced | display;
- RootsFragment.get(getFragmentManager()).onDisplayStateChanged();
- invalidateOptionsMenu();
- }
-
void setDisplayFileSize(boolean display) {
LocalPreferences.setDisplayFileSize(this, display);
mState.showSize = display;
@@ -594,6 +579,28 @@
return super.onKeyDown(keyCode, event);
}
+ @VisibleForTesting
+ public void addEventListener(EventListener listener) {
+ mEventListeners.add(listener);
+ }
+
+ @VisibleForTesting
+ public void removeEventListener(EventListener listener) {
+ mEventListeners.remove(listener);
+ }
+
+ public void notifyDirectoryLoaded(Uri uri) {
+ for (EventListener listener : mEventListeners) {
+ listener.onDirectoryLoaded(uri);
+ }
+ }
+
+ void notifyDirectoryNavigated(Uri uri) {
+ for (EventListener listener : mEventListeners) {
+ listener.onDirectoryNavigated(uri);
+ }
+ }
+
/**
* Toggles focus between the navigation drawer and the directory listing. If the drawer isn't
* locked, open/close it as appropriate.
diff --git a/packages/DocumentsUI/src/com/android/documentsui/CreateDirectoryFragment.java b/packages/DocumentsUI/src/com/android/documentsui/CreateDirectoryFragment.java
index 40bd754..ebc9082 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/CreateDirectoryFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/CreateDirectoryFragment.java
@@ -82,6 +82,9 @@
builder.setNegativeButton(android.R.string.cancel, null);
final AlertDialog dialog = builder.create();
+ // Workaround for the problem - virtual keyboard doesn't show on the phone.
+ Shared.ensureKeyboardPresent(context, dialog);
+
editText.setOnEditorActionListener(
new OnEditorActionListener() {
@Override
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DirectoryLoader.java b/packages/DocumentsUI/src/com/android/documentsui/DirectoryLoader.java
index 13b7b14..d2e918c 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DirectoryLoader.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DirectoryLoader.java
@@ -59,7 +59,6 @@
private CancellationSignal mSignal;
private DirectoryResult mResult;
-
public DirectoryLoader(Context context, int type, RootInfo root, DocumentInfo doc, Uri uri,
int userSortOrder, boolean inSearchMode) {
super(context, ProviderExecutor.forAuthority(root.authority));
@@ -84,6 +83,7 @@
final String authority = mUri.getAuthority();
final DirectoryResult result = new DirectoryResult();
+ result.doc = mDoc;
// Use default document when searching
if (mSearchMode) {
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DirectoryResult.java b/packages/DocumentsUI/src/com/android/documentsui/DirectoryResult.java
index 22e438a..6268643 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DirectoryResult.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DirectoryResult.java
@@ -22,12 +22,15 @@
import android.content.ContentProviderClient;
import android.database.Cursor;
+import com.android.documentsui.model.DocumentInfo;
+
import libcore.io.IoUtils;
public class DirectoryResult implements AutoCloseable {
ContentProviderClient client;
public Cursor cursor;
public Exception exception;
+ public DocumentInfo doc;
public int sortOrder = SORT_ORDER_UNKNOWN;
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DownloadsActivity.java b/packages/DocumentsUI/src/com/android/documentsui/DownloadsActivity.java
index b5d3ea0..2f784cb 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DownloadsActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DownloadsActivity.java
@@ -98,12 +98,10 @@
public boolean onPrepareOptionsMenu(Menu menu) {
super.onPrepareOptionsMenu(menu);
- final MenuItem advanced = menu.findItem(R.id.menu_advanced);
final MenuItem createDir = menu.findItem(R.id.menu_create_dir);
final MenuItem pasteFromCb = menu.findItem(R.id.menu_paste_from_clipboard);
final MenuItem fileSize = menu.findItem(R.id.menu_file_size);
- advanced.setVisible(false);
createDir.setVisible(false);
pasteFromCb.setEnabled(false);
fileSize.setVisible(false);
diff --git a/packages/DocumentsUI/src/com/android/documentsui/EventListener.java b/packages/DocumentsUI/src/com/android/documentsui/EventListener.java
new file mode 100644
index 0000000..c15e9a6
--- /dev/null
+++ b/packages/DocumentsUI/src/com/android/documentsui/EventListener.java
@@ -0,0 +1,32 @@
+/*
+ * 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.
+ */
+
+package com.android.documentsui;
+
+import android.net.Uri;
+import android.support.annotation.Nullable;
+
+public interface EventListener {
+ /**
+ * @param uri Uri navigated to. If recents, then null.
+ */
+ void onDirectoryNavigated(@Nullable Uri uri);
+
+ /**
+ * @param uri Uri of the loaded directory. If recents, then null.
+ */
+ void onDirectoryLoaded(@Nullable Uri uri);
+}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/LocalPreferences.java b/packages/DocumentsUI/src/com/android/documentsui/LocalPreferences.java
index 170fb89..c7c61c3 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/LocalPreferences.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/LocalPreferences.java
@@ -25,17 +25,9 @@
import com.android.documentsui.model.RootInfo;
public class LocalPreferences {
- private static final String KEY_ADVANCED_DEVICES = "advancedDevices";
private static final String KEY_FILE_SIZE = "fileSize";
private static final String ROOT_VIEW_MODE_PREFIX = "rootViewMode-";
- public static boolean getDisplayAdvancedDevices(Context context) {
- boolean defaultAdvanced = context.getResources()
- .getBoolean(R.bool.config_defaultAdvancedDevices);
- return PreferenceManager.getDefaultSharedPreferences(context)
- .getBoolean(KEY_ADVANCED_DEVICES, defaultAdvanced);
- }
-
public static boolean getDisplayFileSize(Context context) {
return PreferenceManager.getDefaultSharedPreferences(context)
.getBoolean(KEY_FILE_SIZE, false);
@@ -47,11 +39,6 @@
.getInt(createKey(root), fallback);
}
- public static void setDisplayAdvancedDevices(Context context, boolean display) {
- PreferenceManager.getDefaultSharedPreferences(context).edit()
- .putBoolean(KEY_ADVANCED_DEVICES, display).apply();
- }
-
public static void setDisplayFileSize(Context context, boolean display) {
PreferenceManager.getDefaultSharedPreferences(context).edit()
.putBoolean(KEY_FILE_SIZE, display).apply();
diff --git a/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java b/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java
index 6856129c..2b7294a 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java
@@ -17,7 +17,6 @@
package com.android.documentsui;
import static com.android.documentsui.Shared.DEBUG;
-import static com.android.documentsui.Shared.TAG;
import android.content.ContentProviderClient;
import android.content.ContentResolver;
@@ -62,6 +61,8 @@
public static final Uri sNotificationUri = Uri.parse(
"content://com.android.documentsui.roots/");
+ private static final String TAG = "RootsCache";
+
private final Context mContext;
private final ContentObserver mObserver;
private OnCacheUpdateListener mCacheUpdateListener;
@@ -417,45 +418,64 @@
static List<RootInfo> getMatchingRoots(Collection<RootInfo> roots, State state) {
final List<RootInfo> matching = new ArrayList<>();
for (RootInfo root : roots) {
- // Exclude read-only devices when creating
- if (state.action == State.ACTION_CREATE && !root.supportsCreate()) continue;
- if (state.action == State.ACTION_PICK_COPY_DESTINATION
- && !root.supportsCreate()) continue;
- // Exclude roots that don't support directory picking
- if (state.action == State.ACTION_OPEN_TREE && !root.supportsChildren()) continue;
- // Exclude advanced devices when not requested
- if (!state.showAdvanced && root.isAdvanced()) continue;
- // Exclude non-local devices when local only
- if (state.localOnly && !root.isLocalOnly()) continue;
- // Exclude downloads roots as it doesn't support directory creation (actually
- // we just don't show them).
- // TODO: Add flag to check the root supports directory creation.
- if (state.directoryCopy && !root.isDownloads()) continue;
- // Only show empty roots when creating, or in browse mode.
- if (root.isEmpty() && (state.action == State.ACTION_OPEN
- || state.action == State.ACTION_GET_CONTENT)) {
- if (DEBUG) Log.i(TAG, "Skipping empty root: " + root);
+ if (DEBUG) Log.d(TAG, "Evaluating " + root);
+
+ if (state.action == State.ACTION_CREATE && !root.supportsCreate()) {
+ if (DEBUG) Log.d(TAG, "Excluding read-only root because: ACTION_CREATE.");
continue;
}
- // Only include roots that serve requested content
+ if (state.action == State.ACTION_PICK_COPY_DESTINATION
+ && !root.supportsCreate()) {
+ if (DEBUG) Log.d(
+ TAG, "Excluding read-only root because: ACTION_PICK_COPY_DESTINATION.");
+ continue;
+ }
+
+ if (state.action == State.ACTION_OPEN_TREE && !root.supportsChildren()) {
+ if (DEBUG) Log.d(
+ TAG, "Excluding root !supportsChildren because: ACTION_OPEN_TREE.");
+ continue;
+ }
+
+ if (state.localOnly && !root.isLocalOnly()) {
+ if (DEBUG) Log.d(TAG, "Excluding root because: unwanted non-local device.");
+ continue;
+ }
+
+ if (state.directoryCopy && root.isDownloads()) {
+ if (DEBUG) Log.d(
+ TAG, "Excluding downloads root because: unsupported directory copy.");
+ continue;
+ }
+
+ if (state.action == State.ACTION_OPEN && root.isEmpty()) {
+ if (DEBUG) Log.d(TAG, "Excluding empty root because: ACTION_OPEN.");
+ continue;
+ }
+
+ if (state.action == State.ACTION_GET_CONTENT && root.isEmpty()) {
+ if (DEBUG) Log.d(TAG, "Excluding empty root because: ACTION_GET_CONTENT.");
+ continue;
+ }
+
final boolean overlap =
MimePredicate.mimeMatches(root.derivedMimeTypes, state.acceptMimes) ||
MimePredicate.mimeMatches(state.acceptMimes, root.derivedMimeTypes);
if (!overlap) {
- continue;
- }
-
- // Exclude roots from the calling package.
- if (state.excludedAuthorities.contains(root.authority)) {
if (DEBUG) Log.d(
- TAG, "Excluding root " + root.authority + " from calling package.");
+ TAG, "Excluding root because: unsupported content types > "
+ + state.acceptMimes);
continue;
}
- if (DEBUG) Log.d(
- TAG, "Including root " + root + " in roots list.");
+ if (state.excludedAuthorities.contains(root.authority)) {
+ if (DEBUG) Log.d(TAG, "Excluding root because: owned by calling package.");
+ continue;
+ }
+
+ if (DEBUG) Log.d(TAG, "Including " + root);
matching.add(root);
}
return matching;
diff --git a/packages/DocumentsUI/src/com/android/documentsui/Shared.java b/packages/DocumentsUI/src/com/android/documentsui/Shared.java
index 99c2d80..26900a7 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/Shared.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/Shared.java
@@ -17,9 +17,12 @@
package com.android.documentsui;
import android.content.Context;
+import android.content.res.Configuration;
import android.text.TextUtils;
import android.text.format.DateUtils;
import android.text.format.Time;
+import android.view.WindowManager;
+import android.app.AlertDialog;
import java.text.Collator;
import java.util.ArrayList;
@@ -155,4 +158,15 @@
return sCollator.compare(lhs, rhs);
}
+
+ public static boolean isHardwareKeyboardAvailable(Context context) {
+ return context.getResources().getConfiguration().keyboard != Configuration.KEYBOARD_NOKEYS;
+ }
+
+ public static void ensureKeyboardPresent(Context context, AlertDialog dialog) {
+ if (!isHardwareKeyboardAvailable(context)) {
+ dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
+ }
+ }
+
}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/State.java b/packages/DocumentsUI/src/com/android/documentsui/State.java
index 62f9ea7..4f460b4 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/State.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/State.java
@@ -82,8 +82,6 @@
public boolean forceSize;
public boolean showSize;
public boolean localOnly;
- public boolean forceAdvanced;
- public boolean showAdvanced;
public boolean restored;
// Indicates that a copy operation (or move) includes a directory.
@@ -181,8 +179,6 @@
out.writeInt(forceSize ? 1 : 0);
out.writeInt(showSize ? 1 : 0);
out.writeInt(localOnly ? 1 : 0);
- out.writeInt(forceAdvanced ? 1 : 0);
- out.writeInt(showAdvanced ? 1 : 0);
out.writeInt(restored ? 1 : 0);
DurableUtils.writeToParcel(out, stack);
out.writeMap(dirState);
@@ -211,8 +207,6 @@
state.forceSize = in.readInt() != 0;
state.showSize = in.readInt() != 0;
state.localOnly = in.readInt() != 0;
- state.forceAdvanced = in.readInt() != 0;
- state.showAdvanced = in.readInt() != 0;
state.restored = in.readInt() != 0;
DurableUtils.readFromParcel(in, state.stack);
in.readMap(state.dirState, loader);
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java
index dfceff8..83838d3 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java
@@ -168,6 +168,7 @@
private GridLayoutManager mLayout;
private int mColumnCount = 1; // This will get updated when layout changes.
+ private LayoutInflater mInflater;
private MessageBar mMessageBar;
private View mProgressBar;
@@ -182,13 +183,12 @@
@Override
public View onCreateView(
LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+ mInflater = inflater;
final View view = inflater.inflate(R.layout.fragment_directory, container, false);
mMessageBar = MessageBar.create(getChildFragmentManager());
mProgressBar = view.findViewById(R.id.progressbar);
-
mEmptyView = view.findViewById(android.R.id.empty);
-
mRecView = (RecyclerView) view.findViewById(R.id.dir_list);
mRecView.setRecyclerListener(
new RecyclerListener() {
@@ -708,13 +708,27 @@
new GetDocumentsTask() {
@Override
void onDocumentsReady(final List<DocumentInfo> docs) {
+
+ TextView message =
+ (TextView) mInflater.inflate(R.layout.dialog_delete_confirmation, null);
+ message.setText(
+ Shared.getQuantityString(
+ getActivity(),
+ R.plurals.delete_confirmation_message,
+ docs.size()));
+
+ // This "insta-hides" files that are being deleted, because
+ // the delete operation may be not execute immediately (it
+ // may be queued up on the FileOperationService.)
+ // To hide the files locally, we call the hide method on the adapter
+ // ...which a live object...cannot be parceled.
+ // For that reason, for now, we implement this dialog NOT
+ // as a fragment (which can survive rotation and have its own state),
+ // but as a simple runtime dialog. So rotating a device with an
+ // active delete dialog...results in that dialog disappearing.
+ // We can do better, but don't have cycles for it now.
new AlertDialog.Builder(getActivity())
- .setTitle(R.string.delete_confirmation_title)
- .setMessage(
- Shared.getQuantityString(
- getActivity(),
- R.plurals.delete_confirmation_message,
- docs.size()))
+ .setView(message)
.setPositiveButton(
android.R.string.yes,
new DialogInterface.OnClickListener() {
@@ -1290,6 +1304,11 @@
showDirectory();
mAdapter.notifyDataSetChanged();
}
+
+ if (!model.isLoading()) {
+ ((BaseActivity) getActivity()).notifyDirectoryLoaded(
+ model.doc != null ? model.doc.derivedUri : null);
+ }
}
@Override
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/DocumentsAdapter.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/DocumentsAdapter.java
index 0930c22..0bbecf9 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/DocumentsAdapter.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/DocumentsAdapter.java
@@ -74,13 +74,6 @@
abstract public SparseArray<String> hide(String... ids);
/**
- * Unhides a set of previously hidden items.
- *
- * @param ids A sparse array of IDs from a previous call to {@link #hide}.
- */
- abstract void unhide(SparseArray<String> ids);
-
- /**
* Returns a class that yields the span size for a particular element. This is
* primarily useful in {@link SectionBreakDocumentsAdapterWrapper} where
* we adjust sizes.
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/ListDocumentHolder.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/ListDocumentHolder.java
index 11f9aa7..8b619b6 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/ListDocumentHolder.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/ListDocumentHolder.java
@@ -123,20 +123,20 @@
mSummary.setVisibility(View.INVISIBLE);
}
- if (docLastModified == -1) {
+ if (docLastModified > 0) {
hasDetails = true;
- mDate.setText(null);
- } else {
mDate.setText(Shared.formatTime(mContext, docLastModified));
+ } else {
+ mDate.setText(null);
}
- if (!state.showSize || docSize == -1) {
+ if (state.showSize && docSize > -1) {
hasDetails = true;
- mSize.setVisibility(View.GONE);
- mDetails.setVisibility(View.GONE);
- } else {
mSize.setVisibility(View.VISIBLE);
mSize.setText(Formatter.formatFileSize(mContext, docSize));
+ } else {
+ mSize.setVisibility(View.GONE);
+ mDetails.setVisibility(View.GONE);
}
mDetails.setVisibility(hasDetails ? View.VISIBLE : View.GONE);
}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/Model.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/Model.java
index 5e55e1a..8170e2a 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/Model.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/Model.java
@@ -64,6 +64,7 @@
@Nullable String info;
@Nullable String error;
+ @Nullable DocumentInfo doc;
/**
* Generates a Model ID for a cursor entry that refers to a document. The Model ID is a unique
@@ -111,6 +112,7 @@
mPositions.clear();
info = null;
error = null;
+ doc = null;
mIsLoading = false;
notifyUpdateListeners();
return;
@@ -125,6 +127,7 @@
mCursor = result.cursor;
mCursorCount = mCursor.getCount();
mSortOrder = result.sortOrder;
+ doc = result.doc;
updateModelData();
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/ModelBackedDocumentsAdapter.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/ModelBackedDocumentsAdapter.java
index 42dba45..2b07339 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/ModelBackedDocumentsAdapter.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/ModelBackedDocumentsAdapter.java
@@ -24,12 +24,12 @@
import android.database.Cursor;
import android.provider.DocumentsContract.Document;
-import android.support.annotation.VisibleForTesting;
import android.util.Log;
import android.util.SparseArray;
import android.view.ViewGroup;
import com.android.documentsui.State;
+
import com.google.common.collect.Sets;
import java.util.ArrayList;
@@ -181,29 +181,6 @@
return hiddenItems;
}
- @VisibleForTesting
- @Override
- public void unhide(SparseArray<String> ids) {
- if (DEBUG) Log.d(TAG, "Unhiding ids: " + ids);
-
- // An ArrayList can shrink at runtime...and in fact
- // it does when we clear it completely.
- // This means we can't call add(pos, id) without
- // first checking the list size.
- List<String> oldIds = mModelIds;
- mModelIds = new ArrayList<>(oldIds.size() + ids.size());
- mModelIds.addAll(oldIds);
-
- // Finally insert the unhidden items.
- for (int i = 0; i < ids.size(); i++) {
- int pos = ids.keyAt(i);
- String id = ids.get(pos);
- mHiddenIds.remove(id);
- mModelIds.add(pos, id);
- notifyItemInserted(pos);
- }
- }
-
@Override
public List<String> getModelIds() {
return mModelIds;
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/RenameDocumentFragment.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/RenameDocumentFragment.java
index 0018d01..884abbb 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/RenameDocumentFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/RenameDocumentFragment.java
@@ -92,6 +92,9 @@
final AlertDialog dialog = builder.create();
+ // Workaround for the problem - virtual keyboard doesn't show on the phone.
+ Shared.ensureKeyboardPresent(context, dialog);
+
mEditText.setOnEditorActionListener(
new OnEditorActionListener() {
@Override
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/SectionBreakDocumentsAdapterWrapper.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/SectionBreakDocumentsAdapterWrapper.java
index 3ee5cfc..b698059 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/SectionBreakDocumentsAdapterWrapper.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/SectionBreakDocumentsAdapterWrapper.java
@@ -169,13 +169,6 @@
}
@Override
- void unhide(SparseArray<String> ids) {
- // NOTE: We hear about these changes and adjust break position
- // in our AdapterDataObserver.
- mDelegate.unhide(ids);
- }
-
- @Override
List<String> getModelIds() {
return mDelegate.getModelIds();
}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/model/RootInfo.java b/packages/DocumentsUI/src/com/android/documentsui/model/RootInfo.java
index 3897058..3eaf10a 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/model/RootInfo.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/model/RootInfo.java
@@ -16,6 +16,7 @@
package com.android.documentsui.model;
+import static com.android.documentsui.Shared.DEBUG;
import static com.android.documentsui.Shared.compareToIgnoreCaseNullable;
import static com.android.documentsui.model.DocumentInfo.getCursorInt;
import static com.android.documentsui.model.DocumentInfo.getCursorLong;
@@ -31,6 +32,7 @@
import android.provider.DocumentsContract;
import android.provider.DocumentsContract.Root;
import android.text.TextUtils;
+import android.util.Log;
import com.android.documentsui.IconUtils;
import com.android.documentsui.R;
@@ -47,6 +49,8 @@
* Representation of a {@link Root}.
*/
public class RootInfo implements Durable, Parcelable, Comparable<RootInfo> {
+
+ private static final String TAG = "RootInfo";
private static final int VERSION_INIT = 1;
private static final int VERSION_DROP_TYPE = 2;
@@ -59,6 +63,8 @@
TYPE_DOWNLOADS,
TYPE_LOCAL,
TYPE_MTP,
+ TYPE_SD,
+ TYPE_USB,
TYPE_OTHER
})
@Retention(RetentionPolicy.SOURCE)
@@ -70,7 +76,9 @@
public static final int TYPE_DOWNLOADS = 5;
public static final int TYPE_LOCAL = 6;
public static final int TYPE_MTP = 7;
- public static final int TYPE_OTHER = 8;
+ public static final int TYPE_SD = 8;
+ public static final int TYPE_USB = 9;
+ public static final int TYPE_OTHER = 10;
public String authority;
public String rootId;
@@ -185,33 +193,40 @@
private void deriveFields() {
derivedMimeTypes = (mimeTypes != null) ? mimeTypes.split("\n") : null;
- // TODO: remove these special case icons
if (isHome()) {
+ derivedType = TYPE_LOCAL;
derivedIcon = R.drawable.ic_root_documents;
- derivedType = TYPE_LOCAL;
- } else if (isExternalStorage()) {
- derivedIcon = R.drawable.ic_root_smartphone;
- derivedType = TYPE_LOCAL;
- // TODO: Apply SD card icon to SD devices.
- } else if (isDownloads()) {
- derivedIcon = R.drawable.ic_root_download;
- derivedType = TYPE_DOWNLOADS;
- } else if (isImages()) {
- derivedIcon = R.drawable.ic_doc_image;
- derivedType = TYPE_IMAGES;
- } else if (isVideos()) {
- derivedIcon = R.drawable.ic_doc_video;
- derivedType = TYPE_VIDEO;
- } else if (isAudio()) {
- derivedIcon = R.drawable.ic_doc_audio;
- derivedType = TYPE_AUDIO;
- } else if (isRecents()) {
- derivedType = TYPE_RECENTS;
} else if (isMtp()) {
derivedType = TYPE_MTP;
+ derivedIcon = R.drawable.ic_usb_storage;
+ } else if (isUsb()) {
+ derivedType = TYPE_USB;
+ derivedIcon = R.drawable.ic_usb_storage;
+ } else if (isSd()) {
+ derivedType = TYPE_SD;
+ derivedIcon = R.drawable.ic_sd_storage;
+ } else if (isExternalStorage()) {
+ derivedType = TYPE_LOCAL;
+ derivedIcon = R.drawable.ic_root_smartphone;
+ } else if (isDownloads()) {
+ derivedType = TYPE_DOWNLOADS;
+ derivedIcon = R.drawable.ic_root_download;
+ } else if (isImages()) {
+ derivedType = TYPE_IMAGES;
+ derivedIcon = R.drawable.ic_doc_image;
+ } else if (isVideos()) {
+ derivedType = TYPE_VIDEO;
+ derivedIcon = R.drawable.ic_doc_video;
+ } else if (isAudio()) {
+ derivedType = TYPE_AUDIO;
+ derivedIcon = R.drawable.ic_doc_audio;
+ } else if (isRecents()) {
+ derivedType = TYPE_RECENTS;
} else {
derivedType = TYPE_OTHER;
}
+
+ if (DEBUG) Log.d(TAG, "Finished deriving fields: " + this);
}
public Uri getUri() {
@@ -283,10 +298,6 @@
return (flags & Root.FLAG_SUPPORTS_SEARCH) != 0;
}
- public boolean isAdvanced() {
- return (flags & Root.FLAG_ADVANCED) != 0;
- }
-
public boolean isLocalOnly() {
return (flags & Root.FLAG_LOCAL_ONLY) != 0;
}
@@ -295,6 +306,14 @@
return (flags & Root.FLAG_EMPTY) != 0;
}
+ public boolean isSd() {
+ return (flags & Root.FLAG_REMOVABLE_SD) != 0;
+ }
+
+ public boolean isUsb() {
+ return (flags & Root.FLAG_REMOVABLE_USB) != 0;
+ }
+
public Drawable loadIcon(Context context) {
if (derivedIcon != 0) {
return context.getDrawable(derivedIcon);
@@ -362,7 +381,14 @@
@Override
public String toString() {
- return "Root{authority=" + authority + ", rootId=" + rootId + ", title=" + title + "}";
+ return "Root{"
+ + "authority=" + authority
+ + ", rootId=" + rootId
+ + ", title=" + title
+ + ", isUsb=" + isUsb()
+ + ", isSd=" + isSd()
+ + ", isMtp=" + isMtp()
+ + "}";
}
public String getDirectoryString() {
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/ActivityTest.java b/packages/DocumentsUI/tests/src/com/android/documentsui/ActivityTest.java
index 4b98aaf..683fd6c 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/ActivityTest.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/ActivityTest.java
@@ -32,8 +32,11 @@
import android.support.test.uiautomator.UiDevice;
import android.support.test.uiautomator.UiObjectNotFoundException;
import android.test.ActivityInstrumentationTestCase2;
+import android.util.Log;
import android.view.MotionEvent;
+import com.android.documentsui.BaseActivity;
+import com.android.documentsui.EventListener;
import com.android.documentsui.bots.DirectoryListBot;
import com.android.documentsui.bots.KeyboardBot;
import com.android.documentsui.bots.RootsListBot;
@@ -64,7 +67,6 @@
public RootInfo rootDir0;
public RootInfo rootDir1;
-
ContentResolver mResolver;
DocumentsProviderHelper mDocsHelper;
ContentProviderClient mClient;
@@ -84,6 +86,23 @@
return rootDir0;
}
+ /**
+ * Returns the authority of the testing provider begin used.
+ * By default it's StubProvider's authority.
+ * @return Authority of the provider.
+ */
+ protected String getTestingProviderAuthority() {
+ return DEFAULT_AUTHORITY;
+ }
+
+ /**
+ * Resolves testing roots.
+ */
+ protected void setupTestingRoots() throws RemoteException {
+ rootDir0 = mDocsHelper.getRoot(ROOT_0_ID);
+ rootDir1 = mDocsHelper.getRoot(ROOT_1_ID);
+ }
+
@Override
public void setUp() throws Exception {
device = UiDevice.getInstance(getInstrumentation());
@@ -95,11 +114,10 @@
Configurator.getInstance().setToolType(MotionEvent.TOOL_TYPE_MOUSE);
mResolver = context.getContentResolver();
- mClient = mResolver.acquireUnstableContentProviderClient(DEFAULT_AUTHORITY);
- mDocsHelper = new DocumentsProviderHelper(DEFAULT_AUTHORITY, mClient);
+ mClient = mResolver.acquireUnstableContentProviderClient(getTestingProviderAuthority());
+ mDocsHelper = new DocumentsProviderHelper(getTestingProviderAuthority(), mClient);
- rootDir0 = mDocsHelper.getRoot(ROOT_0_ID);
- rootDir1 = mDocsHelper.getRoot(ROOT_1_ID);
+ setupTestingRoots();
launchActivity();
resetStorage();
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/RootsCacheTest.java b/packages/DocumentsUI/tests/src/com/android/documentsui/RootsCacheTest.java
index 7d3498e..e73dd8c 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/RootsCacheTest.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/RootsCacheTest.java
@@ -16,6 +16,9 @@
package com.android.documentsui;
+import static com.android.documentsui.RootsCache.getMatchingRoots;
+import static com.google.common.collect.Lists.newArrayList;
+
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.SmallTest;
@@ -28,23 +31,18 @@
@SmallTest
public class RootsCacheTest extends AndroidTestCase {
- private static RootInfo buildForMimeTypes(String... mimeTypes) {
- final RootInfo root = new RootInfo();
- root.derivedMimeTypes = mimeTypes;
- return root;
- }
+ private static RootInfo mNull = new RootInfo();
+ private static RootInfo mEmpty = buildForMimeTypes();
+ private static RootInfo mWild = buildForMimeTypes("*/*");
+ private static RootInfo mImages = buildForMimeTypes("image/*");
+ private static RootInfo mAudio = buildForMimeTypes(
+ "audio/*", "application/ogg", "application/x-flac");
+ private static RootInfo mDocs = buildForMimeTypes(
+ "application/msword", "application/vnd.ms-excel");
+ private static RootInfo mMalformed1 = buildForMimeTypes("meow");
+ private static RootInfo mMalformed2 = buildForMimeTypes("*/meow");
- private RootInfo mNull = new RootInfo();
- private RootInfo mEmpty = buildForMimeTypes();
- private RootInfo mWild = buildForMimeTypes("*/*");
- private RootInfo mImages = buildForMimeTypes("image/*");
- private RootInfo mAudio = buildForMimeTypes("audio/*", "application/ogg", "application/x-flac");
- private RootInfo mDocs = buildForMimeTypes("application/msword", "application/vnd.ms-excel");
- private RootInfo mMalformed1 = buildForMimeTypes("meow");
- private RootInfo mMalformed2 = buildForMimeTypes("*/meow");
-
- private List<RootInfo> mRoots = Lists.newArrayList(
- mNull, mWild, mEmpty, mImages, mAudio, mDocs, mMalformed1, mMalformed2);
+ private List<RootInfo> mRoots;
private State mState;
@@ -52,70 +50,86 @@
protected void setUp() throws Exception {
super.setUp();
+ mRoots = Lists.newArrayList(
+ mNull, mWild, mEmpty, mImages, mAudio, mDocs, mMalformed1, mMalformed2);
+
mState = new State();
mState.action = State.ACTION_OPEN;
- mState.showAdvanced = true;
mState.localOnly = false;
}
- public void testMatchingRootsEverything() throws Exception {
+ public void testMatchingRoots_Everything() throws Exception {
mState.acceptMimes = new String[] { "*/*" };
assertContainsExactly(
- Lists.newArrayList(mNull, mWild, mImages, mAudio, mDocs, mMalformed1, mMalformed2),
- RootsCache.getMatchingRoots(mRoots, mState));
+ newArrayList(mNull, mWild, mImages, mAudio, mDocs, mMalformed1, mMalformed2),
+ getMatchingRoots(mRoots, mState));
}
- public void testMatchingRootsPngOrWild() throws Exception {
+ public void testMatchingRoots_DirectoryCopy() throws Exception {
+ RootInfo downloads = buildForMimeTypes("*/*");
+ downloads.authority = "com.android.providers.downloads.documents";
+ mRoots.add(downloads);
+
+ mState.acceptMimes = new String[] { "*/*" };
+ mState.directoryCopy = true;
+
+ // basically we're asserting that the results don't contain downloads
+ assertContainsExactly(
+ newArrayList(mNull, mWild, mImages, mAudio, mDocs, mMalformed1, mMalformed2),
+ getMatchingRoots(mRoots, mState));
+ }
+
+ public void testMatchingRoots_PngOrWild() throws Exception {
mState.acceptMimes = new String[] { "image/png", "*/*" };
assertContainsExactly(
- Lists.newArrayList(mNull, mWild, mImages, mAudio, mDocs, mMalformed1, mMalformed2),
- RootsCache.getMatchingRoots(mRoots, mState));
+ newArrayList(mNull, mWild, mImages, mAudio, mDocs, mMalformed1, mMalformed2),
+ getMatchingRoots(mRoots, mState));
}
- public void testMatchingRootsAudioWild() throws Exception {
+ public void testMatchingRoots_AudioWild() throws Exception {
mState.acceptMimes = new String[] { "audio/*" };
assertContainsExactly(
- Lists.newArrayList(mNull, mWild, mAudio),
- RootsCache.getMatchingRoots(mRoots, mState));
+ newArrayList(mNull, mWild, mAudio),
+ getMatchingRoots(mRoots, mState));
}
- public void testMatchingRootsAudioWildOrImageWild() throws Exception {
+ public void testMatchingRoots_AudioWildOrImageWild() throws Exception {
mState.acceptMimes = new String[] { "audio/*", "image/*" };
assertContainsExactly(
- Lists.newArrayList(mNull, mWild, mAudio, mImages),
- RootsCache.getMatchingRoots(mRoots, mState));
+ newArrayList(mNull, mWild, mAudio, mImages),
+ getMatchingRoots(mRoots, mState));
}
- public void testMatchingRootsAudioSpecific() throws Exception {
+ public void testMatchingRoots_AudioSpecific() throws Exception {
mState.acceptMimes = new String[] { "audio/mpeg" };
assertContainsExactly(
- Lists.newArrayList(mNull, mWild, mAudio),
- RootsCache.getMatchingRoots(mRoots, mState));
+ newArrayList(mNull, mWild, mAudio),
+ getMatchingRoots(mRoots, mState));
}
- public void testMatchingRootsDocument() throws Exception {
+ public void testMatchingRoots_Document() throws Exception {
mState.acceptMimes = new String[] { "application/msword" };
assertContainsExactly(
- Lists.newArrayList(mNull, mWild, mDocs),
- RootsCache.getMatchingRoots(mRoots, mState));
+ newArrayList(mNull, mWild, mDocs),
+ getMatchingRoots(mRoots, mState));
}
- public void testMatchingRootsApplication() throws Exception {
+ public void testMatchingRoots_Application() throws Exception {
mState.acceptMimes = new String[] { "application/*" };
assertContainsExactly(
- Lists.newArrayList(mNull, mWild, mAudio, mDocs),
- RootsCache.getMatchingRoots(mRoots, mState));
+ newArrayList(mNull, mWild, mAudio, mDocs),
+ getMatchingRoots(mRoots, mState));
}
- public void testMatchingRootsFlacOrPng() throws Exception {
+ public void testMatchingRoots_FlacOrPng() throws Exception {
mState.acceptMimes = new String[] { "application/x-flac", "image/png" };
assertContainsExactly(
- Lists.newArrayList(mNull, mWild, mAudio, mImages),
- RootsCache.getMatchingRoots(mRoots, mState));
+ newArrayList(mNull, mWild, mAudio, mImages),
+ getMatchingRoots(mRoots, mState));
}
public void testExcludedAuthorities() throws Exception {
- final List<RootInfo> roots = Lists.newArrayList();
+ final List<RootInfo> roots = newArrayList();
// Set up some roots
for (int i = 0; i < 5; ++i) {
@@ -124,7 +138,7 @@
roots.add(root);
}
// Make some allowed authorities
- List<RootInfo> allowedRoots = Lists.newArrayList(
+ List<RootInfo> allowedRoots = newArrayList(
roots.get(0), roots.get(2), roots.get(4));
// Set up the excluded authority list
for (RootInfo root: roots) {
@@ -136,7 +150,7 @@
assertContainsExactly(
allowedRoots,
- RootsCache.getMatchingRoots(roots, mState));
+ getMatchingRoots(roots, mState));
}
private static void assertContainsExactly(List<?> expected, List<?> actual) {
@@ -145,4 +159,10 @@
assertTrue(actual.contains(o));
}
}
+
+ private static RootInfo buildForMimeTypes(String... mimeTypes) {
+ final RootInfo root = new RootInfo();
+ root.derivedMimeTypes = mimeTypes;
+ return root;
+ }
}
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/ModelBackedDocumentsAdapterTest.java b/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/ModelBackedDocumentsAdapterTest.java
index 2244be9..adc8141 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/ModelBackedDocumentsAdapterTest.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/ModelBackedDocumentsAdapterTest.java
@@ -73,28 +73,6 @@
assertEquals(mModel.getItemCount() - 2, mAdapter.getItemCount());
}
- // Tests that the items can be hidden and unhidden.
- public void testUnhide_ItemCount() {
- List<String> ids = mModel.getModelIds();
- SparseArray<String> hidden = mAdapter.hide(ids.toArray(new String[ids.size()]));
- mAdapter.unhide(hidden);
- assertEquals(mModel.getItemCount(), mAdapter.getItemCount());
- }
-
- // Tests that the items can be hidden and unhidden.
- public void testUnhide_PreservesOrder() {
- List<String> ids = mModel.getModelIds();
- SparseArray<String> hidden = mAdapter.hide(
- ids.get(0), ids.get(1), ids.get(5), ids.get(9));
- mAdapter.unhide(hidden);
-
- // Finally ensure the restored items are in the original order
- // by checking them against the model.
- for (int i = 0; i < mAdapter.getItemCount(); i++) {
- assertEquals(mModel.idForPosition(i), mAdapter.getModelId(i));
- }
- }
-
private final class TestEnvironment implements DocumentsAdapter.Environment {
private final Context testContext;
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/TestDocumentsAdapter.java b/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/TestDocumentsAdapter.java
index 267f47d..e170dbb 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/TestDocumentsAdapter.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/TestDocumentsAdapter.java
@@ -61,11 +61,6 @@
}
@Override
- void unhide(SparseArray<String> ids) {
- throw new UnsupportedOperationException();
- }
-
- @Override
public DocumentHolder onCreateViewHolder(ViewGroup parent, int viewType) {
throw new UnsupportedOperationException();
}
diff --git a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
index 97527dd..9a51b05 100644
--- a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
+++ b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
@@ -34,6 +34,7 @@
import android.os.ParcelFileDescriptor;
import android.os.ParcelFileDescriptor.OnCloseListener;
import android.os.UserHandle;
+import android.os.storage.DiskInfo;
import android.os.storage.StorageManager;
import android.os.storage.VolumeInfo;
import android.provider.DocumentsContract;
@@ -41,6 +42,7 @@
import android.provider.DocumentsContract.Root;
import android.provider.DocumentsProvider;
import android.provider.MediaStore;
+import android.provider.Settings;
import android.support.provider.DocumentArchiveHelper;
import android.text.TextUtils;
import android.util.ArrayMap;
@@ -62,6 +64,7 @@
public class ExternalStorageProvider extends DocumentsProvider {
private static final String TAG = "ExternalStorage";
+ private static final boolean DEBUG = false;
private static final boolean LOG_INOTIFY = false;
public static final String AUTHORITY = "com.android.externalstorage.documents";
@@ -136,10 +139,25 @@
if (volume.getType() == VolumeInfo.TYPE_EMULATED) {
// We currently only support a single emulated volume mounted at
// a time, and it's always considered the primary
+ if (DEBUG) Log.d(TAG, "Found primary volume: " + volume);
rootId = ROOT_ID_PRIMARY_EMULATED;
+
if (VolumeInfo.ID_EMULATED_INTERNAL.equals(volume.getId())) {
- title = getContext().getString(R.string.root_internal_storage);
+ // This is basically the user's primary device storage.
+ // Use device name for the volume since this is likely same thing
+ // the user sees when they mount their phone on another device.
+ String deviceName = Settings.Global.getString(
+ getContext().getContentResolver(), Settings.Global.DEVICE_NAME);
+
+ // Device name should always be set. In case it isn't, though,
+ // fall back to a localized "Internal Storage" string.
+ title = !TextUtils.isEmpty(deviceName)
+ ? deviceName
+ : getContext().getString(R.string.root_internal_storage);
} else {
+ // This should cover all other storage devices, like an SD card
+ // or USB OTG drive plugged in. Using getBestVolumeDescription()
+ // will give us a nice string like "Samsung SD card" or "SanDisk USB drive"
final VolumeInfo privateVol = mStorageManager.findPrivateForEmulated(volume);
title = mStorageManager.getBestVolumeDescription(privateVol);
}
@@ -167,10 +185,17 @@
root.flags = Root.FLAG_LOCAL_ONLY
| Root.FLAG_SUPPORTS_SEARCH | Root.FLAG_SUPPORTS_IS_CHILD;
+ final DiskInfo disk = volume.getDisk();
+ if (DEBUG) Log.d(TAG, "Disk for root " + rootId + " is " + disk);
+ if (disk != null && disk.isSd()) {
+ root.flags |= Root.FLAG_REMOVABLE_SD;
+ } else if (disk != null && disk.isUsb()) {
+ root.flags |= Root.FLAG_REMOVABLE_USB;
+ }
+
if (volume.isPrimary()) {
// save off the primary volume for subsequent "Home" dir initialization.
primaryVolume = volume;
- root.flags |= Root.FLAG_ADVANCED;
}
// Dunno when this would NOT be the case, but never hurts to be correct.
if (volume.isMountedWritable()) {
@@ -193,8 +218,9 @@
}
}
- // Finally, if primary storage is available we add the "Home" directory,
- // creating it as needed.
+ // Finally, if primary storage is available we add the "Documents" directory.
+ // If I recall correctly the actual directory is created on demand
+ // by calling either getPathForUser, or getInternalPathForUser.
if (primaryVolume != null && primaryVolume.isVisible()) {
final RootInfo root = new RootInfo();
root.rootId = ROOT_ID_HOME;
@@ -211,8 +237,7 @@
root.flags |= Root.FLAG_SUPPORTS_CREATE;
}
- // Create the "Home" directory on disk, but don't the localized root.title
- // since the directories shouldn't be localized.
+ // Create the "Documents" directory on disk (don't use the localized title).
root.visiblePath = new File(
primaryVolume.getPathForUser(userId), Environment.DIRECTORY_DOCUMENTS);
root.path = new File(
diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
index 64f5cc6..4b62f24 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
@@ -731,7 +731,10 @@
// The activity is a component name, therefore it is one or none.
if (resolvedActivities.get(0).activityInfo.exported) {
- intent.putExtra(PrintService.EXTRA_PRINT_JOB_INFO, mPrintJob);
+ PrintJobInfo.Builder printJobBuilder = new PrintJobInfo.Builder(mPrintJob);
+ printJobBuilder.setPages(mSelectedPages);
+
+ intent.putExtra(PrintService.EXTRA_PRINT_JOB_INFO, printJobBuilder.build());
intent.putExtra(PrintService.EXTRA_PRINTER_INFO, printer);
intent.putExtra(PrintService.EXTRA_PRINT_DOCUMENT_INFO,
mPrintedDocument.getDocumentInfo().info);
@@ -759,10 +762,14 @@
// Take the advanced options without interpretation.
mPrintJob.setAdvancedOptions(printJobInfo.getAdvancedOptions());
- // Take copies without interpretation as the advanced print dialog
- // cannot create a print job info with invalid copies.
- mCopiesEditText.setText(String.valueOf(printJobInfo.getCopies()));
- mPrintJob.setCopies(printJobInfo.getCopies());
+ if (printJobInfo.getCopies() < 1) {
+ Log.w(LOG_TAG, "Cannot apply return value from advanced options activity. Copies " +
+ "must be 1 or more. Actual value is: " + printJobInfo.getCopies() + ". " +
+ "Ignoring.");
+ } else {
+ mCopiesEditText.setText(String.valueOf(printJobInfo.getCopies()));
+ mPrintJob.setCopies(printJobInfo.getCopies());
+ }
PrintAttributes currAttributes = mPrintJob.getAttributes();
PrintAttributes newAttributes = printJobInfo.getAttributes();
@@ -771,7 +778,7 @@
// Take the media size only if the current printer supports is.
MediaSize oldMediaSize = currAttributes.getMediaSize();
MediaSize newMediaSize = newAttributes.getMediaSize();
- if (!oldMediaSize.equals(newMediaSize)) {
+ if (newMediaSize != null && !oldMediaSize.equals(newMediaSize)) {
final int mediaSizeCount = mMediaSizeSpinnerAdapter.getCount();
MediaSize newMediaSizePortrait = newAttributes.getMediaSize().asPortrait();
for (int i = 0; i < mediaSizeCount; i++) {
diff --git a/packages/SettingsLib/res/drawable/ic_info.xml b/packages/SettingsLib/res/drawable/ic_info.xml
new file mode 100644
index 0000000..afe7e6b
--- /dev/null
+++ b/packages/SettingsLib/res/drawable/ic_info.xml
@@ -0,0 +1,25 @@
+<!--
+ 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24"
+ android:tint="?android:attr/colorAccent">
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z"/>
+</vector>
diff --git a/packages/SettingsLib/res/drawable/ic_settings_lock_outline.xml b/packages/SettingsLib/res/drawable/ic_settings_lock_outline.xml
deleted file mode 100644
index b3d7cf9..0000000
--- a/packages/SettingsLib/res/drawable/ic_settings_lock_outline.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?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.
--->
-
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="21dp"
- android:height="21dp"
- android:viewportWidth="21.0"
- android:viewportHeight="21.0"
- android:tint="?android:attr/colorAccent">
- <path
- android:fillColor="@android:color/white"
- android:pathData="M8,16c1.1,0,2-0.9,2-2s-0.9-2-2-2s-2,0.9-2,2S6.9,16,8,16zM14,7h-1V5c0-2.8-2.2-5-5-5S3,2.2,3,5v2H2C0.9,7,0,7.9,0,9v10c0,1.1,0.9,2,2,2h12c1.1,0,2-0.9,2-2V9C16,7.9,15.1,7,14,7z M4.9,5c0-1.7,1.4-3.1,3.1-3.1s3.1,1.4,3.1,3.1v2H4.9V5z M14,19H2V9h12V19z" />
-</vector>
diff --git a/packages/SettingsLib/res/layout/restricted_icon.xml b/packages/SettingsLib/res/layout/restricted_icon.xml
new file mode 100644
index 0000000..d57fb80
--- /dev/null
+++ b/packages/SettingsLib/res/layout/restricted_icon.xml
@@ -0,0 +1,21 @@
+<?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.
+-->
+<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/restricted_icon"
+ android:layout_width="@dimen/restricted_icon_size"
+ android:layout_height="@dimen/restricted_icon_size"
+ android:src="@drawable/ic_info"
+ android:gravity="end|center_vertical" />
\ No newline at end of file
diff --git a/packages/SettingsLib/res/layout/restricted_switch_widget.xml b/packages/SettingsLib/res/layout/restricted_switch_widget.xml
new file mode 100644
index 0000000..6183812
--- /dev/null
+++ b/packages/SettingsLib/res/layout/restricted_switch_widget.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.
+-->
+<merge xmlns:android="http://schemas.android.com/apk/res/android">
+ <ImageView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/restricted_icon"
+ android:layout_width="@dimen/restricted_icon_size"
+ android:layout_height="@dimen/restricted_icon_size"
+ android:src="@drawable/ic_info"
+ android:gravity="end|center_vertical" />
+ <!-- Based off frameworks/base/core/res/res/layout/preference_widget_switch.xml -->
+ <Switch xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+android:id/switch_widget"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:focusable="false"
+ android:clickable="false"
+ android:background="@null" />
+</merge>
\ No newline at end of file
diff --git a/packages/SettingsLib/res/values-es/strings.xml b/packages/SettingsLib/res/values-es/strings.xml
index 57a749d..a01d2e9 100644
--- a/packages/SettingsLib/res/values-es/strings.xml
+++ b/packages/SettingsLib/res/values-es/strings.xml
@@ -278,7 +278,7 @@
<string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"Ejecuta procesadores de WebView en un proceso aislado."</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"Implementación de WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Establecer implementación de WebView"</string>
- <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"La implementación de WebView seleccionada no es válida porque la lista de opciones de implementación no estaba activada. Esta ya debería estar actualizada."</string>
+ <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"La implementación de WebView seleccionada no es válida porque la lista de opciones de implementación estaba inactiva. Esta ya debería estar actualizada."</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Convertir a cifrado de archivo"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Convertir…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Ya está cifrado"</string>
diff --git a/packages/SettingsLib/res/values-fa/strings.xml b/packages/SettingsLib/res/values-fa/strings.xml
index a683c55..0a2d111 100644
--- a/packages/SettingsLib/res/values-fa/strings.xml
+++ b/packages/SettingsLib/res/values-fa/strings.xml
@@ -274,11 +274,11 @@
<string name="inactive_app_active_summary" msgid="4174921824958516106">"فعال. برای تغییر حالت ضربه بزنید."</string>
<string name="runningservices_settings_title" msgid="8097287939865165213">"سرویسهای در حال اجرا"</string>
<string name="runningservices_settings_summary" msgid="854608995821032748">"مشاهده و کنترل سرویسهای در حال اجرای فعلی"</string>
- <string name="enable_webview_multiprocess" msgid="3405948012467585908">"فعال کردن WebView چند پردازشی"</string>
- <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"اجرای تولیدکننده تصویر WebView در یک پردازش مجزا."</string>
- <string name="select_webview_provider_title" msgid="4628592979751918907">"اجرای WebView"</string>
- <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"تنظیم اجرای WebView"</string>
- <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"اجرای WebView انتخابی نامعتبر است چون فهرست گزینههای اجرای انتخابی قدیمی شده است. این فهرست اکنون باید بهروزرسانی شود."</string>
+ <string name="enable_webview_multiprocess" msgid="3405948012467585908">"فعال کردن وبنما چند پردازشی"</string>
+ <string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"اجرای تولیدکننده تصویر وبنما در یک پردازش مجزا."</string>
+ <string name="select_webview_provider_title" msgid="4628592979751918907">"اجرای وبنما"</string>
+ <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"تنظیم اجرای وبنما"</string>
+ <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"اجرای وبنما انتخابی نامعتبر است چون فهرست گزینههای اجرای انتخابی قدیمی شده است. این فهرست اکنون باید بهروزرسانی شود."</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"تبدیل به رمزگذاری برحسب فایل"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"تبدیل…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"از قبل به رمزگذاری بر حسب فایل تبدیل شده است"</string>
diff --git a/packages/SettingsLib/res/values-ky-rKG/strings.xml b/packages/SettingsLib/res/values-ky-rKG/strings.xml
index e05d82e2..178d47e 100644
--- a/packages/SettingsLib/res/values-ky-rKG/strings.xml
+++ b/packages/SettingsLib/res/values-ky-rKG/strings.xml
@@ -278,7 +278,7 @@
<string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"WebView рендерерлерин корголгон процессте иштетүү."</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"WebView аткарылышы"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"WebView аткарылышын коюу"</string>
- <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"Аткарууларды тандоо тизмеси эскирип кеткендиктен тандалган WebView аткарылышы жараксыз. Тизме азыр жаңыртылышы керек."</string>
+ <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"Тандалган WebView кызматы колдоого алынбайт. Кызматтардын тизмеси эскирип калгандыктан ал азыр жаңыртылат."</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Файл шифрлөөсүнө айландыруу"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Айландыруу…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Файл мурунтан эле шифрленген"</string>
diff --git a/packages/SettingsLib/res/values-ta-rIN/strings.xml b/packages/SettingsLib/res/values-ta-rIN/strings.xml
index adc75e9..fac31df 100644
--- a/packages/SettingsLib/res/values-ta-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-ta-rIN/strings.xml
@@ -102,7 +102,7 @@
<string name="tts_default_rate_title" msgid="6030550998379310088">"பேச்சு வீதம்"</string>
<string name="tts_default_rate_summary" msgid="4061815292287182801">"பேசப்படும் உரையின் வேகம்"</string>
<string name="tts_default_pitch_title" msgid="6135942113172488671">"ஒலித்திறன்"</string>
- <string name="tts_default_pitch_summary" msgid="1944885882882650009">"தொகுக்கப்பட்ட உரையின் டோன் பாதிக்கப்படும்"</string>
+ <string name="tts_default_pitch_summary" msgid="1944885882882650009">"உருவாக்கப்படும் பேச்சின் டோன் பாதிக்கப்படும்"</string>
<string name="tts_default_lang_title" msgid="8018087612299820556">"மொழி"</string>
<string name="tts_lang_use_system" msgid="2679252467416513208">"முறைமையின் மொழியைப் பயன்படுத்து"</string>
<string name="tts_lang_not_selected" msgid="7395787019276734765">"மொழி தேர்ந்தெடுக்கப்படவில்லை"</string>
diff --git a/packages/SettingsLib/res/values-zh-rCN/strings.xml b/packages/SettingsLib/res/values-zh-rCN/strings.xml
index 53bd985..4001d2c 100644
--- a/packages/SettingsLib/res/values-zh-rCN/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rCN/strings.xml
@@ -278,7 +278,7 @@
<string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"在独立进程中运行 WebView 渲染程序。"</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"WebView 实现"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"设置 WebView 实现"</string>
- <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"所选的 WebView 实现无效,因为相关的实现选项列表已过时。请立即更新这份列表。"</string>
+ <string name="select_webview_provider_toast_text" msgid="8168796505966635684">"所选的 WebView 实现无效,因为实现选项列表已过时。请立即更新列表。"</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"转换为文件加密"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"转换…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"文件已加密"</string>
diff --git a/packages/SettingsLib/res/values/dimens.xml b/packages/SettingsLib/res/values/dimens.xml
index 9f78e87..c3b3cfc 100644
--- a/packages/SettingsLib/res/values/dimens.xml
+++ b/packages/SettingsLib/res/values/dimens.xml
@@ -33,8 +33,8 @@
<dimen name="user_spinner_item_height">56dp</dimen>
<!-- Lock icon for preferences locked by admin -->
- <dimen name="restricted_lock_icon_size">16dp</dimen>
- <dimen name="restricted_lock_icon_padding">4dp</dimen>
+ <dimen name="restricted_icon_size">16dp</dimen>
+ <dimen name="restricted_icon_padding">4dp</dimen>
<dimen name="wifi_preference_badge_padding">8dip</dimen>
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index 72fa939..ae2c6e7 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -773,6 +773,11 @@
<!-- Summary for settings preference disabled by administrator [CHAR LIMIT=50] -->
<string name="disabled_by_admin_summary_text">Controlled by admin</string>
+ <!-- Summary for switch preference to denote it is switched on [CHAR LIMIT=50] -->
+ <string name="enabled_by_admin">Enabled by administrator</string>
+ <!-- Summary for switch preference to denote it is switched on [CHAR LIMIT=50] -->
+ <string name="disabled_by_admin">Disabled by administrator</string>
+
<!-- Option in navigation drawer that leads to Settings main screen [CHAR LIMIT=30] -->
<string name="home">Home</string>
diff --git a/packages/SettingsLib/src/com/android/settingslib/RestrictedDropDownPreference.java b/packages/SettingsLib/src/com/android/settingslib/RestrictedDropDownPreference.java
index c2f885d..4c0450e 100644
--- a/packages/SettingsLib/src/com/android/settingslib/RestrictedDropDownPreference.java
+++ b/packages/SettingsLib/src/com/android/settingslib/RestrictedDropDownPreference.java
@@ -49,7 +49,7 @@
mRestrictedPadlock = RestrictedLockUtils.getRestrictedPadlock(context);
mRestrictedPadlockPadding = context.getResources().getDimensionPixelSize(
- R.dimen.restricted_lock_icon_padding);
+ R.dimen.restricted_icon_padding);
}
private final OnItemSelectedListener mItemSelectedListener = new OnItemSelectedListener() {
diff --git a/packages/SettingsLib/src/com/android/settingslib/RestrictedLockImageSpan.java b/packages/SettingsLib/src/com/android/settingslib/RestrictedLockImageSpan.java
index e63130d..360a34c 100644
--- a/packages/SettingsLib/src/com/android/settingslib/RestrictedLockImageSpan.java
+++ b/packages/SettingsLib/src/com/android/settingslib/RestrictedLockImageSpan.java
@@ -36,7 +36,7 @@
mContext = context;
mExtraPadding = mContext.getResources().getDimensionPixelSize(
- R.dimen.restricted_lock_icon_padding);
+ R.dimen.restricted_icon_padding);
mRestrictedPadlock = RestrictedLockUtils.getRestrictedPadlock(mContext);
}
@@ -53,7 +53,7 @@
// Add extra padding before the padlock.
float transX = x + mExtraPadding;
- float transY = bottom - drawable.getBounds().bottom - paint.getFontMetricsInt().descent;
+ float transY = (bottom - drawable.getBounds().bottom) / 2.0f;
canvas.translate(transX, transY);
drawable.draw(canvas);
diff --git a/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtils.java b/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtils.java
index 6d29c5f..d0c249f 100644
--- a/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtils.java
@@ -49,9 +49,9 @@
* @return drawables for displaying with settings that are locked by a device admin.
*/
public static Drawable getRestrictedPadlock(Context context) {
- Drawable restrictedPadlock = context.getDrawable(R.drawable.ic_settings_lock_outline);
+ Drawable restrictedPadlock = context.getDrawable(R.drawable.ic_info);
final int iconSize = context.getResources().getDimensionPixelSize(
- R.dimen.restricted_lock_icon_size);
+ R.dimen.restricted_icon_size);
restrictedPadlock.setBounds(0, 0, iconSize, iconSize);
return restrictedPadlock;
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/RestrictedPreference.java b/packages/SettingsLib/src/com/android/settingslib/RestrictedPreference.java
index 810f6eb..e69497a 100644
--- a/packages/SettingsLib/src/com/android/settingslib/RestrictedPreference.java
+++ b/packages/SettingsLib/src/com/android/settingslib/RestrictedPreference.java
@@ -23,6 +23,7 @@
import android.support.v7.preference.PreferenceManager;
import android.support.v7.preference.PreferenceViewHolder;
import android.util.AttributeSet;
+import android.view.View;
import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
@@ -36,6 +37,7 @@
public RestrictedPreference(Context context, AttributeSet attrs,
int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
+ setWidgetLayoutResource(R.layout.restricted_icon);
mHelper = new RestrictedPreferenceHelper(context, this, attrs);
}
@@ -56,6 +58,10 @@
public void onBindViewHolder(PreferenceViewHolder holder) {
super.onBindViewHolder(holder);
mHelper.onBindViewHolder(holder);
+ final View restrictedIcon = holder.findViewById(R.id.restricted_icon);
+ if (restrictedIcon != null) {
+ restrictedIcon.setVisibility(isDisabledByAdmin() ? View.VISIBLE : View.GONE);
+ }
}
@Override
diff --git a/packages/SettingsLib/src/com/android/settingslib/RestrictedPreferenceHelper.java b/packages/SettingsLib/src/com/android/settingslib/RestrictedPreferenceHelper.java
index 227b1e8..0c0af24 100644
--- a/packages/SettingsLib/src/com/android/settingslib/RestrictedPreferenceHelper.java
+++ b/packages/SettingsLib/src/com/android/settingslib/RestrictedPreferenceHelper.java
@@ -54,7 +54,7 @@
mRestrictedPadlock = RestrictedLockUtils.getRestrictedPadlock(mContext);
mRestrictedPadlockPadding = mContext.getResources().getDimensionPixelSize(
- R.dimen.restricted_lock_icon_padding);
+ R.dimen.restricted_icon_padding);
if (attrs != null) {
final TypedArray attributes = context.obtainStyledAttributes(attrs,
@@ -91,12 +91,8 @@
* Modify PreferenceViewHolder to add padlock if restriction is disabled.
*/
public void onBindViewHolder(PreferenceViewHolder holder) {
- final TextView titleView = (TextView) holder.findViewById(android.R.id.title);
- if (titleView != null) {
- RestrictedLockUtils.setTextViewPadlock(mContext, titleView, mDisabledByAdmin);
- if (mDisabledByAdmin) {
- holder.itemView.setEnabled(true);
- }
+ if (mDisabledByAdmin) {
+ holder.itemView.setEnabled(true);
}
if (mUseAdminDisabledSummary) {
final TextView summaryView = (TextView) holder.findViewById(android.R.id.summary);
diff --git a/packages/SettingsLib/src/com/android/settingslib/RestrictedSwitchPreference.java b/packages/SettingsLib/src/com/android/settingslib/RestrictedSwitchPreference.java
index 6cae8aa..f381286 100644
--- a/packages/SettingsLib/src/com/android/settingslib/RestrictedSwitchPreference.java
+++ b/packages/SettingsLib/src/com/android/settingslib/RestrictedSwitchPreference.java
@@ -23,6 +23,8 @@
import android.support.v7.preference.PreferenceViewHolder;
import android.support.v14.preference.SwitchPreference;
import android.util.AttributeSet;
+import android.view.View;
+import android.widget.TextView;
import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
@@ -36,6 +38,7 @@
public RestrictedSwitchPreference(Context context, AttributeSet attrs,
int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
+ setWidgetLayoutResource(R.layout.restricted_switch_widget);
mHelper = new RestrictedPreferenceHelper(context, this, attrs);
}
@@ -56,6 +59,20 @@
public void onBindViewHolder(PreferenceViewHolder holder) {
super.onBindViewHolder(holder);
mHelper.onBindViewHolder(holder);
+ final View restrictedIcon = holder.findViewById(R.id.restricted_icon);
+ final View switchWidget = holder.findViewById(android.R.id.switch_widget);
+ if (restrictedIcon != null) {
+ restrictedIcon.setVisibility(isDisabledByAdmin() ? View.VISIBLE : View.GONE);
+ }
+ if (switchWidget != null) {
+ switchWidget.setVisibility(isDisabledByAdmin() ? View.GONE : View.VISIBLE);
+ }
+ final TextView summaryView = (TextView) holder.findViewById(android.R.id.summary);
+ if (summaryView != null && isDisabledByAdmin()) {
+ summaryView.setText(
+ isChecked() ? R.string.enabled_by_admin : R.string.disabled_by_admin);
+ summaryView.setVisibility(View.VISIBLE);
+ }
}
@Override
diff --git a/packages/SettingsLib/src/com/android/settingslib/SuggestionParser.java b/packages/SettingsLib/src/com/android/settingslib/SuggestionParser.java
index 1859207..741b0ea 100644
--- a/packages/SettingsLib/src/com/android/settingslib/SuggestionParser.java
+++ b/packages/SettingsLib/src/com/android/settingslib/SuggestionParser.java
@@ -25,6 +25,12 @@
import android.util.Log;
import android.util.Pair;
import android.util.Xml;
+import android.provider.Settings;
+import android.accounts.Account;
+import android.accounts.AccountManager;
+import android.content.ContentValues;
+import android.content.pm.PackageManager;
+import android.content.res.Resources;
import android.view.InflateException;
import com.android.settingslib.drawer.Tile;
import com.android.settingslib.drawer.TileUtils;
@@ -42,6 +48,12 @@
// If defined, only returns this suggestion if the feature is supported.
public static final String META_DATA_REQUIRE_FEATURE = "com.android.settings.require_feature";
+ // If defined, only display this optional step if an account of that type exists.
+ private static final String META_DATA_REQUIRE_ACCOUNT = "com.android.settings.require_account";
+
+ // If defined and not true, do not should optional step.
+ private static final String META_DATA_IS_SUPPORTED = "com.android.settings.is_supported";
+
/**
* Allows suggestions to appear after a certain number of days, and to re-appear if dismissed.
* For instance:
@@ -110,7 +122,10 @@
TileUtils.getTilesForIntent(mContext, new UserHandle(UserHandle.myUserId()), intent,
addCache, null, suggestions, true, false);
for (int i = countBefore; i < suggestions.size(); i++) {
- if (!isAvailable(suggestions.get(i)) || isDismissed(suggestions.get(i))) {
+ if (!isAvailable(suggestions.get(i)) ||
+ !isSupported(suggestions.get(i)) ||
+ !satisfiesRequiredAccount(suggestions.get(i)) ||
+ isDismissed(suggestions.get(i))) {
suggestions.remove(i--);
}
}
@@ -124,7 +139,10 @@
item = last;
}
}
- suggestions.add(item);
+ // If category is marked as done, do not add any item.
+ if (!isCategoryDone(category.category)) {
+ suggestions.add(item);
+ }
}
}
@@ -136,6 +154,41 @@
return true;
}
+ public boolean satisfiesRequiredAccount(Tile suggestion) {
+ String requiredAccountType = suggestion.metaData.getString(META_DATA_REQUIRE_ACCOUNT);
+ if (requiredAccountType == null) {
+ return true;
+ }
+ AccountManager accountManager = AccountManager.get(mContext);
+ Account[] accounts = accountManager.getAccountsByType(requiredAccountType);
+ return accounts.length > 0;
+ }
+
+ public boolean isSupported(Tile suggestion) {
+ int isSupportedResource = suggestion.metaData.getInt(META_DATA_IS_SUPPORTED);
+ try {
+ if (suggestion.intent == null) {
+ return false;
+ }
+ final Resources res = mContext.getPackageManager().getResourcesForActivity(
+ suggestion.intent.getComponent());
+ return isSupportedResource != 0 ? res.getBoolean(isSupportedResource) : true;
+ } catch (PackageManager.NameNotFoundException e) {
+ Log.w(TAG, "Cannot find resources for " + suggestion.intent.getComponent());
+ return false;
+ }
+ }
+
+ public boolean isCategoryDone(String category) {
+ String name = Settings.Secure.COMPLETED_CATEGORY_PREFIX + category;
+ return Settings.Secure.getInt(mContext.getContentResolver(), name, 0) != 0;
+ }
+
+ public void markCategoryDone(String category) {
+ String name = Settings.Secure.COMPLETED_CATEGORY_PREFIX + category;
+ Settings.Secure.putInt(mContext.getContentResolver(), name, 1);
+ }
+
private boolean isDismissed(Tile suggestion) {
Object dismissObj = suggestion.metaData.get(META_DATA_DISMISS_CONTROL);
if (dismissObj == null) {
diff --git a/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java b/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java
index a578055..7a1c741 100644
--- a/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java
+++ b/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java
@@ -69,16 +69,18 @@
long startTime = System.currentTimeMillis();
- getWindow().addFlags(LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
- getWindow().addFlags(LayoutParams.FLAG_TRANSLUCENT_STATUS);
- requestWindowFeature(Window.FEATURE_NO_TITLE);
+ TypedArray theme = getTheme().obtainStyledAttributes(android.R.styleable.Theme);
+ if (!theme.getBoolean(android.R.styleable.Theme_windowNoTitle, false)) {
+ getWindow().addFlags(LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
+ getWindow().addFlags(LayoutParams.FLAG_TRANSLUCENT_STATUS);
+ requestWindowFeature(Window.FEATURE_NO_TITLE);
+ }
super.setContentView(R.layout.settings_with_drawer);
mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
if (mDrawerLayout == null) {
return;
}
Toolbar toolbar = (Toolbar) findViewById(R.id.action_bar);
- TypedArray theme = getTheme().obtainStyledAttributes(android.R.styleable.Theme);
if (theme.getBoolean(android.R.styleable.Theme_windowNoTitle, false)) {
toolbar.setVisibility(View.GONE);
mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index 9842e28..a424d55 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -1128,10 +1128,15 @@
private PackageInfo getCallingPackageInfoOrThrow(int userId) {
try {
- return mPackageManager.getPackageInfo(getCallingPackage(), 0, userId);
+ PackageInfo packageInfo = mPackageManager.getPackageInfo(
+ getCallingPackage(), 0, userId);
+ if (packageInfo != null) {
+ return packageInfo;
+ }
} catch (RemoteException e) {
- throw new IllegalStateException("Calling package doesn't exist");
+ /* ignore */
}
+ throw new IllegalStateException("Calling package doesn't exist");
}
private int getGroupParentLocked(int userId) {
diff --git a/packages/Shell/res/values-af/strings.xml b/packages/Shell/res/values-af/strings.xml
index 9d399c1..f86b551 100644
--- a/packages/Shell/res/values-af/strings.xml
+++ b/packages/Shell/res/values-af/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Kon nie skermkiekie neem nie."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Foutverslag <xliff:g id="ID">#%d</xliff:g> se besonderhede"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"Lêernaam"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"Titel"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"Gedetailleerde beskrywing"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"Fouttitel"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"Foutopsomming"</string>
+ <string name="save" msgid="4781509040564835759">"Stoor"</string>
</resources>
diff --git a/packages/Shell/res/values-am/strings.xml b/packages/Shell/res/values-am/strings.xml
index 2545222..55c5390 100644
--- a/packages/Shell/res/values-am/strings.xml
+++ b/packages/Shell/res/values-am/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"ቅጽበታዊ ገጽ እይታ ሊነሳ አይችልም"</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"የሳንካ ሪፖርት <xliff:g id="ID">#%d</xliff:g> ዝርዝሮች"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"የፋይል ስም"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"ርዕስ"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"ዝርዝር መግለጫ"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"የሳንካ ርዕስ"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"የሳንካ ማጠቃለያ"</string>
+ <string name="save" msgid="4781509040564835759">"አስቀምጥ"</string>
</resources>
diff --git a/packages/Shell/res/values-ar/strings.xml b/packages/Shell/res/values-ar/strings.xml
index 7593110..f0af8ce 100644
--- a/packages/Shell/res/values-ar/strings.xml
+++ b/packages/Shell/res/values-ar/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"تعذر التقاط لقطة الشاشة."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"تفاصيل تقرير الخطأ <xliff:g id="ID">#%d</xliff:g>"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"اسم الملف"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"العنوان"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"وصف تفصيلي"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"عنوان الخطأ"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"ملخص الخطأ"</string>
+ <string name="save" msgid="4781509040564835759">"حفظ"</string>
</resources>
diff --git a/packages/Shell/res/values-az-rAZ/strings.xml b/packages/Shell/res/values-az-rAZ/strings.xml
index 9130255..6d375fe 100644
--- a/packages/Shell/res/values-az-rAZ/strings.xml
+++ b/packages/Shell/res/values-az-rAZ/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Displey görüntüsü əlçatan deyil."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Baq hesabatı <xliff:g id="ID">#%d</xliff:g> detalları"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"Fayl adı"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"Başlıq"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"Ətraflı təsvir"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"Baq başlığı"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"Baq xülasə"</string>
+ <string name="save" msgid="4781509040564835759">"Yadda saxlayın"</string>
</resources>
diff --git a/packages/Shell/res/values-b+sr+Latn/strings.xml b/packages/Shell/res/values-b+sr+Latn/strings.xml
index 597e545..ad84941 100644
--- a/packages/Shell/res/values-b+sr+Latn/strings.xml
+++ b/packages/Shell/res/values-b+sr+Latn/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Snimanje ekrana nije uspelo."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Detalji izveštaja o grešci <xliff:g id="ID">#%d</xliff:g>"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"Naziv datoteke"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"Naslov"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"Detaljni opis"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"Naslov greške"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"Rezime greške"</string>
+ <string name="save" msgid="4781509040564835759">"Sačuvaj"</string>
</resources>
diff --git a/packages/Shell/res/values-bg/strings.xml b/packages/Shell/res/values-bg/strings.xml
index 6ca7914..e543839 100644
--- a/packages/Shell/res/values-bg/strings.xml
+++ b/packages/Shell/res/values-bg/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Екранната снимка не можа да бъде направена."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Подробности за сигнала за програмна грешка „<xliff:g id="ID">#%d</xliff:g>“"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"Име на файла"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"Заглавие"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"Подробно описание"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"Заглавие на сигнала за програмна грешка"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"Обобщена информация за сигнала за програмна грешка"</string>
+ <string name="save" msgid="4781509040564835759">"Запазване"</string>
</resources>
diff --git a/packages/Shell/res/values-bn-rBD/strings.xml b/packages/Shell/res/values-bn-rBD/strings.xml
index 5390315..bba778d 100644
--- a/packages/Shell/res/values-bn-rBD/strings.xml
+++ b/packages/Shell/res/values-bn-rBD/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"স্ক্রীনশট নেওয়া যায়নি৷"</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"ত্রুটির প্রতিবেদন <xliff:g id="ID">#%d</xliff:g> এর বিশদ বিবরণ"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"ফাইলের নাম"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"শীর্ষক"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"বিস্তারিত বিবরণ"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"ত্রুটির শীর্ষক"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"ত্রুটির সারাংশ"</string>
+ <string name="save" msgid="4781509040564835759">"সংরক্ষণ করুন"</string>
</resources>
diff --git a/packages/Shell/res/values-bs-rBA/strings.xml b/packages/Shell/res/values-bs-rBA/strings.xml
index 903c2ab..54be955 100644
--- a/packages/Shell/res/values-bs-rBA/strings.xml
+++ b/packages/Shell/res/values-bs-rBA/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Ekran nije moguće snimiti."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Detalji izvještaja o grešci <xliff:g id="ID">#%d</xliff:g>"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"Naziv fajla"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"Naslov"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"Detaljan opis"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"Naslov greške"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"Sažetak greške"</string>
+ <string name="save" msgid="4781509040564835759">"Sačuvaj"</string>
</resources>
diff --git a/packages/Shell/res/values-ca/strings.xml b/packages/Shell/res/values-ca/strings.xml
index 0836946..a92177e 100644
--- a/packages/Shell/res/values-ca/strings.xml
+++ b/packages/Shell/res/values-ca/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"No s\'ha pogut fer la captura de pantalla."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Detalls de l\'informe d\'errors <xliff:g id="ID">#%d</xliff:g>"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"Nom del fitxer"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"Títol"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"Descripció detallada"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"Títol de l\'error"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"Resum d\'errors"</string>
+ <string name="save" msgid="4781509040564835759">"Desa"</string>
</resources>
diff --git a/packages/Shell/res/values-cs/strings.xml b/packages/Shell/res/values-cs/strings.xml
index 215ec87..6f7549a 100644
--- a/packages/Shell/res/values-cs/strings.xml
+++ b/packages/Shell/res/values-cs/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Snímek obrazovky se nepodařilo pořídit."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Podrobnosti zprávy o chybě <xliff:g id="ID">#%d</xliff:g>"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"Název souboru"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"Název"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"Podrobný popis"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"Název chyby"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"Přehled chyby"</string>
+ <string name="save" msgid="4781509040564835759">"Uložit"</string>
</resources>
diff --git a/packages/Shell/res/values-da/strings.xml b/packages/Shell/res/values-da/strings.xml
index e956d3a..72a9a99 100644
--- a/packages/Shell/res/values-da/strings.xml
+++ b/packages/Shell/res/values-da/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Der kunne ikke tages et skærmbillede."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Oplysninger om fejlrapporten <xliff:g id="ID">#%d</xliff:g>"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"Filnavn"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"Titel"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"Detaljeret beskrivelse"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"Fejlrapportens titel"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"Oversigt over fejl"</string>
+ <string name="save" msgid="4781509040564835759">"Gem"</string>
</resources>
diff --git a/packages/Shell/res/values-de/strings.xml b/packages/Shell/res/values-de/strings.xml
index 07f8898..f848c9d 100644
--- a/packages/Shell/res/values-de/strings.xml
+++ b/packages/Shell/res/values-de/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Screenshot konnte nicht aufgenommen werden."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Details zum Fehlerbericht <xliff:g id="ID">#%d</xliff:g>"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"Dateiname"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"Titel"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"Detaillierte Beschreibung"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"Titel des Programmfehlers"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"Zusammenfassung des Programmfehlers"</string>
+ <string name="save" msgid="4781509040564835759">"Speichern"</string>
</resources>
diff --git a/packages/Shell/res/values-el/strings.xml b/packages/Shell/res/values-el/strings.xml
index 6746976..0c04809 100644
--- a/packages/Shell/res/values-el/strings.xml
+++ b/packages/Shell/res/values-el/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Δεν ήταν δυνατή η λήψη του στιγμιότυπου οθόνης."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Λεπτομέρειες της αναφοράς σφάλματος <xliff:g id="ID">#%d</xliff:g>"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"Όνομα αρχείου"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"Τίτλος"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"Αναλυτική περιγραφή"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"Τίτλος σφάλματος"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"Περίληψη σφάλματος"</string>
+ <string name="save" msgid="4781509040564835759">"Αποθήκευση"</string>
</resources>
diff --git a/packages/Shell/res/values-en-rAU/strings.xml b/packages/Shell/res/values-en-rAU/strings.xml
index ac681e2..ad637f5 100644
--- a/packages/Shell/res/values-en-rAU/strings.xml
+++ b/packages/Shell/res/values-en-rAU/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Screenshot could not be taken."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Bug report <xliff:g id="ID">#%d</xliff:g> details"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"Filename"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"Title"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"Detailed description"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"Bug title"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"Bug summary"</string>
+ <string name="save" msgid="4781509040564835759">"Save"</string>
</resources>
diff --git a/packages/Shell/res/values-en-rGB/strings.xml b/packages/Shell/res/values-en-rGB/strings.xml
index ac681e2..ad637f5 100644
--- a/packages/Shell/res/values-en-rGB/strings.xml
+++ b/packages/Shell/res/values-en-rGB/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Screenshot could not be taken."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Bug report <xliff:g id="ID">#%d</xliff:g> details"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"Filename"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"Title"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"Detailed description"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"Bug title"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"Bug summary"</string>
+ <string name="save" msgid="4781509040564835759">"Save"</string>
</resources>
diff --git a/packages/Shell/res/values-en-rIN/strings.xml b/packages/Shell/res/values-en-rIN/strings.xml
index ac681e2..ad637f5 100644
--- a/packages/Shell/res/values-en-rIN/strings.xml
+++ b/packages/Shell/res/values-en-rIN/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Screenshot could not be taken."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Bug report <xliff:g id="ID">#%d</xliff:g> details"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"Filename"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"Title"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"Detailed description"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"Bug title"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"Bug summary"</string>
+ <string name="save" msgid="4781509040564835759">"Save"</string>
</resources>
diff --git a/packages/Shell/res/values-es-rUS/strings.xml b/packages/Shell/res/values-es-rUS/strings.xml
index 96ca14c..a9a1e08 100644
--- a/packages/Shell/res/values-es-rUS/strings.xml
+++ b/packages/Shell/res/values-es-rUS/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"No se pudo tomar la captura de pantalla."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Detalles del informe de errores <xliff:g id="ID">#%d</xliff:g>"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"Nombre del archivo"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"Título"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"Descripción completa"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"Título del error"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"Resumen del error"</string>
+ <string name="save" msgid="4781509040564835759">"Guardar"</string>
</resources>
diff --git a/packages/Shell/res/values-es/strings.xml b/packages/Shell/res/values-es/strings.xml
index 00874c6..b82d372 100644
--- a/packages/Shell/res/values-es/strings.xml
+++ b/packages/Shell/res/values-es/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"No se puede realizar la captura de pantalla."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Detalles del informe de errores <xliff:g id="ID">#%d</xliff:g>"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"Nombre de archivo"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"Título"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"Descripción completa"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"Nombre del informe de errores"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"Resumen del informe de errores"</string>
+ <string name="save" msgid="4781509040564835759">"Guardar"</string>
</resources>
diff --git a/packages/Shell/res/values-et-rEE/strings.xml b/packages/Shell/res/values-et-rEE/strings.xml
index bc469bc..cdb774a0 100644
--- a/packages/Shell/res/values-et-rEE/strings.xml
+++ b/packages/Shell/res/values-et-rEE/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Ekraanipilti ei saanud teha."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Veaaruande <xliff:g id="ID">#%d</xliff:g> üksikasjad"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"Faili nimi"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"Pealkiri"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"Üksikasjalik kirjeldus"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"Vea pealkiri"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"Vea kokkuvõte"</string>
+ <string name="save" msgid="4781509040564835759">"Salvesta"</string>
</resources>
diff --git a/packages/Shell/res/values-eu-rES/strings.xml b/packages/Shell/res/values-eu-rES/strings.xml
index 614f17e..42dfe27 100644
--- a/packages/Shell/res/values-eu-rES/strings.xml
+++ b/packages/Shell/res/values-eu-rES/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Ezin izan da atera pantaila-argazkia."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Akatsen <xliff:g id="ID">#%d</xliff:g> txostenaren xehetasunak"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"Fitxategi-izena"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"Izena"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"Azalpen xehatua"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"Akatsaren izena"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"Akatsaren laburpena"</string>
+ <string name="save" msgid="4781509040564835759">"Gorde"</string>
</resources>
diff --git a/packages/Shell/res/values-fa/strings.xml b/packages/Shell/res/values-fa/strings.xml
index ab00562..e825f3a 100644
--- a/packages/Shell/res/values-fa/strings.xml
+++ b/packages/Shell/res/values-fa/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"نمیتوان عکس صفحهنمایش گرفت."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"جزئیات گزارش اشکال <xliff:g id="ID">#%d</xliff:g>"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"نام فایل"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"عنوان"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"جزئیات دقیق"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"عنوان اشکال"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"خلاصه اشکال"</string>
+ <string name="save" msgid="4781509040564835759">"ذخیره کردن"</string>
</resources>
diff --git a/packages/Shell/res/values-fi/strings.xml b/packages/Shell/res/values-fi/strings.xml
index be7aabd..8c67c66 100644
--- a/packages/Shell/res/values-fi/strings.xml
+++ b/packages/Shell/res/values-fi/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Kuvakaappauksen tallentaminen epäonnistui."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Virheraportin <xliff:g id="ID">#%d</xliff:g> tiedot"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"Tiedostonimi"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"Otsikko"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"Yksityiskohtainen kuvaus"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"Virheen nimi"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"Virheen yhteenveto"</string>
+ <string name="save" msgid="4781509040564835759">"Tallenna"</string>
</resources>
diff --git a/packages/Shell/res/values-fr-rCA/strings.xml b/packages/Shell/res/values-fr-rCA/strings.xml
index 7d9f97d..3daa120 100644
--- a/packages/Shell/res/values-fr-rCA/strings.xml
+++ b/packages/Shell/res/values-fr-rCA/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Une erreur s\'est produite lors de la saisie d\'écran."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Détails du rapport de bogue <xliff:g id="ID">#%d</xliff:g>"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"Nom de fichier"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"Titre"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"Description détaillée"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"Titre du bogue"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"Sommaire des bogues"</string>
+ <string name="save" msgid="4781509040564835759">"Enregistrer"</string>
</resources>
diff --git a/packages/Shell/res/values-fr/strings.xml b/packages/Shell/res/values-fr/strings.xml
index 74025d9..c512aca 100644
--- a/packages/Shell/res/values-fr/strings.xml
+++ b/packages/Shell/res/values-fr/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Impossible d\'effectuer une capture d\'écran."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Informations sur le rapport de bug \"<xliff:g id="ID">#%d</xliff:g>\""</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"Nom de fichier"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"Titre"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"Description détaillée"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"Titre du bug"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"Résumé du bug"</string>
+ <string name="save" msgid="4781509040564835759">"Enregistrer"</string>
</resources>
diff --git a/packages/Shell/res/values-gl-rES/strings.xml b/packages/Shell/res/values-gl-rES/strings.xml
index d3be7c5..ea95c97 100644
--- a/packages/Shell/res/values-gl-rES/strings.xml
+++ b/packages/Shell/res/values-gl-rES/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Non se puido realizar a captura de pantalla."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Detalles do informe de erros <xliff:g id="ID">#%d</xliff:g>"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"Nome do ficheiro"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"Título"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"Descrición detallada"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"Título do informe de erros"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"Resumo do informe de erros"</string>
+ <string name="save" msgid="4781509040564835759">"Gardar"</string>
</resources>
diff --git a/packages/Shell/res/values-gu-rIN/strings.xml b/packages/Shell/res/values-gu-rIN/strings.xml
index 45df7b3..1436c3d 100644
--- a/packages/Shell/res/values-gu-rIN/strings.xml
+++ b/packages/Shell/res/values-gu-rIN/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"સ્ક્રીનશોટ લઇ શકાયો નથી."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"બગ રિપોર્ટ <xliff:g id="ID">#%d</xliff:g> ની વિગતો"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"ફાઇલનું નામ"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"શીર્ષક"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"વિગતવાર વર્ણન"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"બગનું શીર્ષક"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"બગનો સારાંશ"</string>
+ <string name="save" msgid="4781509040564835759">"સાચવો"</string>
</resources>
diff --git a/packages/Shell/res/values-hi/strings.xml b/packages/Shell/res/values-hi/strings.xml
index 8858bc3..9a735f2 100644
--- a/packages/Shell/res/values-hi/strings.xml
+++ b/packages/Shell/res/values-hi/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"स्क्रीनशॉट नहीं लिया जा सका."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"बग रिपोर्ट <xliff:g id="ID">#%d</xliff:g> के विवरण"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"फ़ाइल नाम"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"शीर्षक"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"विस्तृत वर्णन"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"बग शीर्षक"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"बग सारांश"</string>
+ <string name="save" msgid="4781509040564835759">"सहेजें"</string>
</resources>
diff --git a/packages/Shell/res/values-hr/strings.xml b/packages/Shell/res/values-hr/strings.xml
index cb03f9c..71d50b8 100644
--- a/packages/Shell/res/values-hr/strings.xml
+++ b/packages/Shell/res/values-hr/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Snimanje zaslona nije uspjelo."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Pojedinosti izvješća o programskoj pogrešci <xliff:g id="ID">#%d</xliff:g>"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"Naziv datoteke"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"Naslov"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"Detaljan opis"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"Naslov izvješća o programskoj pogrešci"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"Sažetak izvješća o programskoj pogrešci"</string>
+ <string name="save" msgid="4781509040564835759">"Spremi"</string>
</resources>
diff --git a/packages/Shell/res/values-hu/strings.xml b/packages/Shell/res/values-hu/strings.xml
index 390cd2f..cf10315 100644
--- a/packages/Shell/res/values-hu/strings.xml
+++ b/packages/Shell/res/values-hu/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Nem sikerült elkészíteni a képernyőképet."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Hibajelentés (<xliff:g id="ID">#%d</xliff:g>) részletei"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"Fájlnév"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"Név"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"Részletes leírás"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"Hibajelentés címe"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"Hibajelentés összefoglalója"</string>
+ <string name="save" msgid="4781509040564835759">"Mentés"</string>
</resources>
diff --git a/packages/Shell/res/values-hy-rAM/strings.xml b/packages/Shell/res/values-hy-rAM/strings.xml
index 68478ab..1cf5c94 100644
--- a/packages/Shell/res/values-hy-rAM/strings.xml
+++ b/packages/Shell/res/values-hy-rAM/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Չհաջողվեց ստանալ էկրանի պատկերը:"</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"<xliff:g id="ID">#%d</xliff:g> վրիպակի զեկույցի մանրամասները"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"Ֆայլի անունը"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"Անվանումը"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"Մանրամասն նկարագրություն"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"Վրիպակի զեկույցի վերնագիրը"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"Վրիպակի զեկույցի ամփոփագիրը"</string>
+ <string name="save" msgid="4781509040564835759">"Պահել"</string>
</resources>
diff --git a/packages/Shell/res/values-in/strings.xml b/packages/Shell/res/values-in/strings.xml
index 4416fc7..1e8fe87 100644
--- a/packages/Shell/res/values-in/strings.xml
+++ b/packages/Shell/res/values-in/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Tangkapan layar tidak dapat diambil."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Detail laporan bug <xliff:g id="ID">#%d</xliff:g>"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"Nama file"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"Judul"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"Deskripsi detail"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"Judul bug"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"Ringkasan bug"</string>
+ <string name="save" msgid="4781509040564835759">"Simpan"</string>
</resources>
diff --git a/packages/Shell/res/values-is-rIS/strings.xml b/packages/Shell/res/values-is-rIS/strings.xml
index 0d43719..afcea59 100644
--- a/packages/Shell/res/values-is-rIS/strings.xml
+++ b/packages/Shell/res/values-is-rIS/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Ekki tókst að taka skjámynd."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Upplýsingar villutilkynningar <xliff:g id="ID">#%d</xliff:g>"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"Skráarheiti"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"Titill"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"Ítarleg lýsing"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"Heiti villu"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"Villusamantekt"</string>
+ <string name="save" msgid="4781509040564835759">"Vista"</string>
</resources>
diff --git a/packages/Shell/res/values-it/strings.xml b/packages/Shell/res/values-it/strings.xml
index fc9383a..d7ac9a5 100644
--- a/packages/Shell/res/values-it/strings.xml
+++ b/packages/Shell/res/values-it/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Impossibile acquisire lo screenshot."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Dettagli sulla segnalazione di bug <xliff:g id="ID">#%d</xliff:g>"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"Nome file"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"Titolo"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"Descrizione dettagliata"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"Titolo bug"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"Riepilogo bug"</string>
+ <string name="save" msgid="4781509040564835759">"Salva"</string>
</resources>
diff --git a/packages/Shell/res/values-iw/strings.xml b/packages/Shell/res/values-iw/strings.xml
index 335a2e8..fd64ee1 100644
--- a/packages/Shell/res/values-iw/strings.xml
+++ b/packages/Shell/res/values-iw/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"לא ניתן היה לצלם מסך."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"פרטי הדוח על הבאג <xliff:g id="ID">#%d</xliff:g>"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"שם קובץ"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"כותרת"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"תיאור מפורט"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"כותרת הבאג"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"סיכום הבאג"</string>
+ <string name="save" msgid="4781509040564835759">"שמור"</string>
</resources>
diff --git a/packages/Shell/res/values-ja/strings.xml b/packages/Shell/res/values-ja/strings.xml
index b98b05f..050c5df 100644
--- a/packages/Shell/res/values-ja/strings.xml
+++ b/packages/Shell/res/values-ja/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"スクリーンショットを撮影できませんでした。"</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"バグレポート <xliff:g id="ID">#%d</xliff:g> の詳細"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"ファイル名"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"タイトル"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"詳細説明"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"バグのタイトル"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"バグの概要"</string>
+ <string name="save" msgid="4781509040564835759">"保存"</string>
</resources>
diff --git a/packages/Shell/res/values-ka-rGE/strings.xml b/packages/Shell/res/values-ka-rGE/strings.xml
index 24d83a4..8c5c6fb 100644
--- a/packages/Shell/res/values-ka-rGE/strings.xml
+++ b/packages/Shell/res/values-ka-rGE/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"ეკრანის ანაბეჭდის გადაღება ვერ მოხერხდა."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"ხარვეზების შესახებ ანგარიში <xliff:g id="ID">#%d</xliff:g>-ის დეტალები"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"ფაილის სახელი"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"სათაური"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"დეტალური აღწერა"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"შეცდომის სათაური"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"შეცდომის რეზიუმე"</string>
+ <string name="save" msgid="4781509040564835759">"შენახვა"</string>
</resources>
diff --git a/packages/Shell/res/values-kk-rKZ/strings.xml b/packages/Shell/res/values-kk-rKZ/strings.xml
index 5878b17..edb2dd0 100644
--- a/packages/Shell/res/values-kk-rKZ/strings.xml
+++ b/packages/Shell/res/values-kk-rKZ/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Скриншот түсіру мүмкін болмады."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"<xliff:g id="ID">#%d</xliff:g> қате туралы есебі туралы мәліметтер"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"Файл атауы"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"Атауы"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"Егжей-тегжейлі сипаттама"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"Қатенің атауы"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"Қате туралы жиынтық мәліметтер"</string>
+ <string name="save" msgid="4781509040564835759">"Сақтау"</string>
</resources>
diff --git a/packages/Shell/res/values-km-rKH/strings.xml b/packages/Shell/res/values-km-rKH/strings.xml
index 9c95e98..ba0de9f 100644
--- a/packages/Shell/res/values-km-rKH/strings.xml
+++ b/packages/Shell/res/values-km-rKH/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"មិនអាចថតរូបថតអេក្រង់បានទេ"</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"ព័ត៌មានលម្អិតពី <xliff:g id="ID">#%d</xliff:g> របាយការណ៍កំហុស"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"ឈ្មោះឯកសារ"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"ចំណងជើង"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"ការពិពណ៌នាលម្អិត"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"ចំណងជើងកំហុស"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"សង្ខេបកំហុស"</string>
+ <string name="save" msgid="4781509040564835759">"រក្សាទុក"</string>
</resources>
diff --git a/packages/Shell/res/values-kn-rIN/strings.xml b/packages/Shell/res/values-kn-rIN/strings.xml
index ce6f3c0..b041f35 100644
--- a/packages/Shell/res/values-kn-rIN/strings.xml
+++ b/packages/Shell/res/values-kn-rIN/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"ಸ್ಕ್ರೀನ್ಶಾಟ್ ತೆಗೆದುಕೊಳ್ಳಲು ಸಾಧ್ಯವಾಗುವುದಿಲ್ಲ."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"ದೋಷ ವರದಿಯ <xliff:g id="ID">#%d</xliff:g> ವಿವರಗಳು"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"ಫೈಲ್ಹೆಸರು"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"ಶೀರ್ಷಿಕೆ"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"ವಿವರವಾದ ವಿವರಣೆ"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"ಬಗ್ ಶೀರ್ಷಿಕೆ"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"ಬಗ್ ಸಾರಾಂಶ"</string>
+ <string name="save" msgid="4781509040564835759">"ಉಳಿಸು"</string>
</resources>
diff --git a/packages/Shell/res/values-ko/strings.xml b/packages/Shell/res/values-ko/strings.xml
index 70df8e2..2a86360 100644
--- a/packages/Shell/res/values-ko/strings.xml
+++ b/packages/Shell/res/values-ko/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"스크린샷을 찍을 수 없습니다."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"버그 신고 <xliff:g id="ID">#%d</xliff:g> 세부정보"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"파일 이름"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"제목"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"자세한 설명"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"버그 제목"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"버그 요약"</string>
+ <string name="save" msgid="4781509040564835759">"저장"</string>
</resources>
diff --git a/packages/Shell/res/values-ky-rKG/strings.xml b/packages/Shell/res/values-ky-rKG/strings.xml
index 49d8d8d..1903109 100644
--- a/packages/Shell/res/values-ky-rKG/strings.xml
+++ b/packages/Shell/res/values-ky-rKG/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Скриншот тартылбай койду."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Мүчүлүштүк тууралуу билдирүүнүн <xliff:g id="ID">#%d</xliff:g> чоо-жайы"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"Файлдын аталышы"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"Аталышы"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"Кененирээк маалымат"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"Мүчүлүштүктүн аталышы"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"Мүчүлүштүктүн корутундусу"</string>
+ <string name="save" msgid="4781509040564835759">"Сактоо"</string>
</resources>
diff --git a/packages/Shell/res/values-lo-rLA/strings.xml b/packages/Shell/res/values-lo-rLA/strings.xml
index 61b06c8..4348250 100644
--- a/packages/Shell/res/values-lo-rLA/strings.xml
+++ b/packages/Shell/res/values-lo-rLA/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"ບໍ່ສາມາດຖ່າຍພາບໜ້າຈໍໄດ້."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"ລາຍລະອຽດຂອງລາຍງານຂໍ້ຜິດພາດ <xliff:g id="ID">#%d</xliff:g>"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"ຊື່ໄຟລ໌"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"ຊື່"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"ຄຳອະທິບາຍແບບລະອຽດ"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"ຊື່ຂໍ້ຜິດພາດ"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"ສະຫຼຸບຂໍ້ຜິດພາດ"</string>
+ <string name="save" msgid="4781509040564835759">"ບັນທຶກ"</string>
</resources>
diff --git a/packages/Shell/res/values-lt/strings.xml b/packages/Shell/res/values-lt/strings.xml
index 3418213..a714efc 100644
--- a/packages/Shell/res/values-lt/strings.xml
+++ b/packages/Shell/res/values-lt/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Nepavyko padaryti ekrano kopijos."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Išsami informacija apie pranešimą apie riktą (<xliff:g id="ID">#%d</xliff:g>)"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"Failo pavadinimas"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"Pavadinimas"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"Išsamus aprašas"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"Rikto pavadinimas"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"Rikto suvestinė"</string>
+ <string name="save" msgid="4781509040564835759">"Išsaugoti"</string>
</resources>
diff --git a/packages/Shell/res/values-lv/strings.xml b/packages/Shell/res/values-lv/strings.xml
index 6108716..880d651 100644
--- a/packages/Shell/res/values-lv/strings.xml
+++ b/packages/Shell/res/values-lv/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Nevarēja veikt ekrānuzņēmumu."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Kļūdas pārskats <xliff:g id="ID">#%d</xliff:g>: detalizēta informācija"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"Faila nosaukums"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"Nosaukums"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"Detalizēts apraksts"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"Kļūdas nosaukums"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"Kļūdas kopsavilkums"</string>
+ <string name="save" msgid="4781509040564835759">"Saglabāt"</string>
</resources>
diff --git a/packages/Shell/res/values-mk-rMK/strings.xml b/packages/Shell/res/values-mk-rMK/strings.xml
index 500196d..478c189 100644
--- a/packages/Shell/res/values-mk-rMK/strings.xml
+++ b/packages/Shell/res/values-mk-rMK/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Не може да се направи слика од екранот."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Детали за извештајот за грешки <xliff:g id="ID">#%d</xliff:g>"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"Име на датотека"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"Наслов"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"Детален опис"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"Наслов на грешката"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"Преглед на грешката"</string>
+ <string name="save" msgid="4781509040564835759">"Зачувај"</string>
</resources>
diff --git a/packages/Shell/res/values-ml-rIN/strings.xml b/packages/Shell/res/values-ml-rIN/strings.xml
index 696aab2..70e6333 100644
--- a/packages/Shell/res/values-ml-rIN/strings.xml
+++ b/packages/Shell/res/values-ml-rIN/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"സ്ക്രീൻഷോട്ട് എടുക്കാൻ കഴിഞ്ഞില്ല."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"ബഗ് റിപ്പോർട്ട് <xliff:g id="ID">#%d</xliff:g> വിശദാംശങ്ങൾ"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"ഫയല്നാമം"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"പേര്"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"വിശദമായ വിവരണം"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"ബഗിന്റെ പേര്"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"ബഗ് സംഗ്രഹം"</string>
+ <string name="save" msgid="4781509040564835759">"സംരക്ഷിക്കുക"</string>
</resources>
diff --git a/packages/Shell/res/values-mn-rMN/strings.xml b/packages/Shell/res/values-mn-rMN/strings.xml
index 62d83cb..49196a2 100644
--- a/packages/Shell/res/values-mn-rMN/strings.xml
+++ b/packages/Shell/res/values-mn-rMN/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Дэлгэцийн зураг авах боломжгүй."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Програмд гарсан алдааны мэдээллийн <xliff:g id="ID">#%d</xliff:g>-ны дэлгэрэнгүй"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"Файлын нэр"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"Гарчиг"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"Дэлгэрэнгүй тайлбар"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"Алдааны нэр"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"Алдааны хураангуй"</string>
+ <string name="save" msgid="4781509040564835759">"Хадгалах"</string>
</resources>
diff --git a/packages/Shell/res/values-mr-rIN/strings.xml b/packages/Shell/res/values-mr-rIN/strings.xml
index e6b2b04..19a8706 100644
--- a/packages/Shell/res/values-mr-rIN/strings.xml
+++ b/packages/Shell/res/values-mr-rIN/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"स्क्रीनशॉट घेणे शक्य झाले नाही."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"दोष अहवाल <xliff:g id="ID">#%d</xliff:g> तपशील"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"फाईलनाव"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"शीर्षक"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"तपशीलवार वर्णन"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"दोष शीर्षक"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"दोष सारांश"</string>
+ <string name="save" msgid="4781509040564835759">"जतन करा"</string>
</resources>
diff --git a/packages/Shell/res/values-ms-rMY/strings.xml b/packages/Shell/res/values-ms-rMY/strings.xml
index 1d04253..c9f5375 100644
--- a/packages/Shell/res/values-ms-rMY/strings.xml
+++ b/packages/Shell/res/values-ms-rMY/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Tangkapan skrin tidak dapat diambil."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Butiran laporan pepijat <xliff:g id="ID">#%d</xliff:g>"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"Nama fail"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"Tajuk"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"Perihalan terperinci"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"Tajuk pepijat"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"Ringkasan pepijat"</string>
+ <string name="save" msgid="4781509040564835759">"Simpan"</string>
</resources>
diff --git a/packages/Shell/res/values-my-rMM/strings.xml b/packages/Shell/res/values-my-rMM/strings.xml
index f63c8c5..4250eda 100644
--- a/packages/Shell/res/values-my-rMM/strings.xml
+++ b/packages/Shell/res/values-my-rMM/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"မျက်နှာပြင် လျှပ်တစ်ပြက်ပုံ မရိုက်နိုင်ပါ"</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"ချွတ်ယွင်းမှုအစီရင်ခံချက် <xliff:g id="ID">#%d</xliff:g> အသေးစိတ်များ"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"ဖိုင်အမည်"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"ခေါင်းစဉ်"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"အသေးစိတ် ဖော်ပြချက်"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"ချွတ်ယွင်းချက် ခေါင်းစဉ်"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"ချွတ်ယွင်းချက် အကျဉ်းချုပ်"</string>
+ <string name="save" msgid="4781509040564835759">"သိမ်းဆည်းပါ"</string>
</resources>
diff --git a/packages/Shell/res/values-nb/strings.xml b/packages/Shell/res/values-nb/strings.xml
index 328e8ae..aa86ae4 100644
--- a/packages/Shell/res/values-nb/strings.xml
+++ b/packages/Shell/res/values-nb/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Skjermdumpen kunne ikke tas."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Detaljer om feilrapporten <xliff:g id="ID">#%d</xliff:g>"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"Filnavn"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"Tittel"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"Detaljert beskrivelse"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"Navn på feil"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"Oppsummering av feil"</string>
+ <string name="save" msgid="4781509040564835759">"Lagre"</string>
</resources>
diff --git a/packages/Shell/res/values-ne-rNP/strings.xml b/packages/Shell/res/values-ne-rNP/strings.xml
index 62bfead..43c2a5c 100644
--- a/packages/Shell/res/values-ne-rNP/strings.xml
+++ b/packages/Shell/res/values-ne-rNP/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"स्क्रिनशट लिन सकिएन।"</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"बग रिपोर्ट <xliff:g id="ID">#%d</xliff:g>का विवरणहरू"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"फाइलको नाम"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"शीर्षक"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"विस्तृत विवरण"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"बगको शीर्षक"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"बगको सारांश"</string>
+ <string name="save" msgid="4781509040564835759">"सुरक्षित गर्नुहोस्"</string>
</resources>
diff --git a/packages/Shell/res/values-nl/strings.xml b/packages/Shell/res/values-nl/strings.xml
index 2f4b215..01fd577 100644
--- a/packages/Shell/res/values-nl/strings.xml
+++ b/packages/Shell/res/values-nl/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Screenshot kan niet worden gemaakt."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Details van bugrapport <xliff:g id="ID">#%d</xliff:g>"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"Bestandsnaam"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"Titel"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"Gedetailleerde beschrijving"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"Titel van bug"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"Overzicht van bug"</string>
+ <string name="save" msgid="4781509040564835759">"Opslaan"</string>
</resources>
diff --git a/packages/Shell/res/values-pa-rIN/strings.xml b/packages/Shell/res/values-pa-rIN/strings.xml
index dc2277f..3494199 100644
--- a/packages/Shell/res/values-pa-rIN/strings.xml
+++ b/packages/Shell/res/values-pa-rIN/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"ਸਕ੍ਰੀਨਸ਼ਾਟ ਨਹੀਂ ਲਿਆ ਜਾ ਸਕਿਆ।"</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"ਬੱਗ ਰਿਪੋਰਟ <xliff:g id="ID">#%d</xliff:g> ਵੇਰਵੇ"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"ਫ਼ਾਈਲ ਨਾਮ"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"ਸਿਰਲੇਖ"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"ਵਿਸਥਾਰ ਸਹਿਤ ਵਰਣਨ"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"ਬੱਗ ਸਿਰਲੇਖ"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"ਬੱਗ ਸਾਰਾਂਸ਼"</string>
+ <string name="save" msgid="4781509040564835759">"ਰੱਖਿਅਤ ਕਰੋ"</string>
</resources>
diff --git a/packages/Shell/res/values-pl/strings.xml b/packages/Shell/res/values-pl/strings.xml
index c585568..91934c9 100644
--- a/packages/Shell/res/values-pl/strings.xml
+++ b/packages/Shell/res/values-pl/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Nie udało się zrobić zrzutu ekranu."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Szczegóły raportu o błędzie <xliff:g id="ID">#%d</xliff:g>"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"Nazwa pliku"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"Tytuł"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"Szczegółowy opis"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"Tytuł raportu o błędzie"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"Podsumowanie raportu o błędzie"</string>
+ <string name="save" msgid="4781509040564835759">"Zapisz"</string>
</resources>
diff --git a/packages/Shell/res/values-pt-rBR/strings.xml b/packages/Shell/res/values-pt-rBR/strings.xml
index fc6e21c..41f4e24 100644
--- a/packages/Shell/res/values-pt-rBR/strings.xml
+++ b/packages/Shell/res/values-pt-rBR/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Não foi possível fazer a captura de tela."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Detalhes do relatório de bugs <xliff:g id="ID">#%d</xliff:g>"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"Nome do arquivo"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"Título"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"Descrição detalhada"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"Título do bug"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"Resumo do bug"</string>
+ <string name="save" msgid="4781509040564835759">"Salvar"</string>
</resources>
diff --git a/packages/Shell/res/values-pt-rPT/strings.xml b/packages/Shell/res/values-pt-rPT/strings.xml
index 252edb1..416db80 100644
--- a/packages/Shell/res/values-pt-rPT/strings.xml
+++ b/packages/Shell/res/values-pt-rPT/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Não foi possível tirar a captura de ecrã."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Detalhes do relatório de erro <xliff:g id="ID">#%d</xliff:g>"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"Nome do ficheiro"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"Título"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"Descrição detalhada"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"Título do erro"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"Resumo de erros"</string>
+ <string name="save" msgid="4781509040564835759">"Guardar"</string>
</resources>
diff --git a/packages/Shell/res/values-pt/strings.xml b/packages/Shell/res/values-pt/strings.xml
index fc6e21c..41f4e24 100644
--- a/packages/Shell/res/values-pt/strings.xml
+++ b/packages/Shell/res/values-pt/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Não foi possível fazer a captura de tela."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Detalhes do relatório de bugs <xliff:g id="ID">#%d</xliff:g>"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"Nome do arquivo"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"Título"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"Descrição detalhada"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"Título do bug"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"Resumo do bug"</string>
+ <string name="save" msgid="4781509040564835759">"Salvar"</string>
</resources>
diff --git a/packages/Shell/res/values-ro/strings.xml b/packages/Shell/res/values-ro/strings.xml
index d720417..4112e60 100644
--- a/packages/Shell/res/values-ro/strings.xml
+++ b/packages/Shell/res/values-ro/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Captura de ecran nu a putut fi făcută."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Detaliile raportului de eroare <xliff:g id="ID">#%d</xliff:g>"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"Numele fișierului"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"Titlu"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"Descriere detaliată"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"Titlul erorii"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"Rezumat privind eroarea"</string>
+ <string name="save" msgid="4781509040564835759">"Salvați"</string>
</resources>
diff --git a/packages/Shell/res/values-ru/strings.xml b/packages/Shell/res/values-ru/strings.xml
index ed5ecaf..ffd2e66 100644
--- a/packages/Shell/res/values-ru/strings.xml
+++ b/packages/Shell/res/values-ru/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Не удалось сделать скриншот"</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Данные отчета об ошибке <xliff:g id="ID">#%d</xliff:g>"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"Название файла"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"Название"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"Подробное описание"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"Название ошибки"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"Описание ошибки"</string>
+ <string name="save" msgid="4781509040564835759">"Сохранить"</string>
</resources>
diff --git a/packages/Shell/res/values-si-rLK/strings.xml b/packages/Shell/res/values-si-rLK/strings.xml
index cd8fba3..807ebb1 100644
--- a/packages/Shell/res/values-si-rLK/strings.xml
+++ b/packages/Shell/res/values-si-rLK/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"තිර රුවක් ගත නොහැකි විය."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"දෝෂ වාර්තා <xliff:g id="ID">#%d</xliff:g> විස්තර"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"ගොනුවේ නම"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"මාතෘකාව"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"සවිස්තර විස්තරය"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"දෝෂ මාතෘකාව"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"දෝෂ සාරාංශය"</string>
+ <string name="save" msgid="4781509040564835759">"සුරකින්න"</string>
</resources>
diff --git a/packages/Shell/res/values-sk/strings.xml b/packages/Shell/res/values-sk/strings.xml
index 23e67f5..a62a6eb 100644
--- a/packages/Shell/res/values-sk/strings.xml
+++ b/packages/Shell/res/values-sk/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Snímku obrazovky sa nepodarilo zaznamenať."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Podrobnosti hlásenia chyby <xliff:g id="ID">#%d</xliff:g>"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"Názov súboru"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"Názov"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"Podrobný popis"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"Názov chyby"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"Súhrn chyby"</string>
+ <string name="save" msgid="4781509040564835759">"Uložiť"</string>
</resources>
diff --git a/packages/Shell/res/values-sl/strings.xml b/packages/Shell/res/values-sl/strings.xml
index 519f3f2..6d1be5a 100644
--- a/packages/Shell/res/values-sl/strings.xml
+++ b/packages/Shell/res/values-sl/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Posnetka zaslon ni bilo mogoče ustvariti."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Podrobnosti poročila o napaki <xliff:g id="ID">#%d</xliff:g>"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"Ime datoteke"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"Naslov"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"Podroben opis"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"Naslov poročila o napakah"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"Povzetek poročila o napakah"</string>
+ <string name="save" msgid="4781509040564835759">"Shrani"</string>
</resources>
diff --git a/packages/Shell/res/values-sq-rAL/strings.xml b/packages/Shell/res/values-sq-rAL/strings.xml
index 5e3c706..ce990e9 100644
--- a/packages/Shell/res/values-sq-rAL/strings.xml
+++ b/packages/Shell/res/values-sq-rAL/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Pamja e ekranit nuk mund të realizohej."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Detajet e raportit të defekteve në kod <xliff:g id="ID">#%d</xliff:g>"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"Emri i skedarit"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"Titulli"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"Përshkrimi i detajuar"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"Titulli i defektit në kod"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"Përmbledhja e defekteve në kod"</string>
+ <string name="save" msgid="4781509040564835759">"Ruaj"</string>
</resources>
diff --git a/packages/Shell/res/values-sr/strings.xml b/packages/Shell/res/values-sr/strings.xml
index 55119b6..0157a25 100644
--- a/packages/Shell/res/values-sr/strings.xml
+++ b/packages/Shell/res/values-sr/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Снимање екрана није успело."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Детаљи извештаја о грешци <xliff:g id="ID">#%d</xliff:g>"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"Назив датотеке"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"Наслов"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"Детаљни опис"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"Наслов грешке"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"Резиме грешке"</string>
+ <string name="save" msgid="4781509040564835759">"Сачувај"</string>
</resources>
diff --git a/packages/Shell/res/values-sv/strings.xml b/packages/Shell/res/values-sv/strings.xml
index 085f57e..88af0db 100644
--- a/packages/Shell/res/values-sv/strings.xml
+++ b/packages/Shell/res/values-sv/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Det gick inte att ta skrämdump."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Information för felrapporten <xliff:g id="ID">#%d</xliff:g>"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"Filnamn"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"Namn"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"Detaljerad beskrivning"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"Felets titel"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"Sammanfattning av felet"</string>
+ <string name="save" msgid="4781509040564835759">"Spara"</string>
</resources>
diff --git a/packages/Shell/res/values-sw/strings.xml b/packages/Shell/res/values-sw/strings.xml
index c5a8ef1..01df55e 100644
--- a/packages/Shell/res/values-sw/strings.xml
+++ b/packages/Shell/res/values-sw/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Haikupiga picha ya skrini."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Maelezo ya ripoti ya hitilafu ya <xliff:g id="ID">#%d</xliff:g>"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"Jina la faili"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"Kichwa"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"Maelezo ya kina"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"Jina la hitilafu"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"Muhtasari wa hitilafu"</string>
+ <string name="save" msgid="4781509040564835759">"Hifadhi"</string>
</resources>
diff --git a/packages/Shell/res/values-ta-rIN/strings.xml b/packages/Shell/res/values-ta-rIN/strings.xml
index 7ef89e2..8238d25 100644
--- a/packages/Shell/res/values-ta-rIN/strings.xml
+++ b/packages/Shell/res/values-ta-rIN/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"ஸ்கிரீன் ஷாட்டை எடுக்க முடியவில்லை."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"பிழை அறிக்கை <xliff:g id="ID">#%d</xliff:g> இன் விவரங்கள்"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"கோப்புப்பெயர்"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"தலைப்பு"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"விரிவான விளக்கம்"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"பிழைத் தலைப்பு"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"பிழை குறித்த சுருக்க விவரம்"</string>
+ <string name="save" msgid="4781509040564835759">"சேமி"</string>
</resources>
diff --git a/packages/Shell/res/values-te-rIN/strings.xml b/packages/Shell/res/values-te-rIN/strings.xml
index 6ba816b..3ed1f95 100644
--- a/packages/Shell/res/values-te-rIN/strings.xml
+++ b/packages/Shell/res/values-te-rIN/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"స్క్రీన్షాట్ను తీయడం సాధ్యపడలేదు."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"బగ్ నివేదిక <xliff:g id="ID">#%d</xliff:g> వివరాలు"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"ఫైల్ పేరు"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"శీర్షిక"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"సమగ్ర వివరణ"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"బగ్ శీర్షిక"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"బగ్ సారాంశం"</string>
+ <string name="save" msgid="4781509040564835759">"సేవ్ చేయి"</string>
</resources>
diff --git a/packages/Shell/res/values-th/strings.xml b/packages/Shell/res/values-th/strings.xml
index d68ca26..f28bac6 100644
--- a/packages/Shell/res/values-th/strings.xml
+++ b/packages/Shell/res/values-th/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"ไม่สามารถจับภาพหน้าจอได้"</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"รายละเอียดรายงานข้อบกพร่อง <xliff:g id="ID">#%d</xliff:g>"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"ชื่อไฟล์"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"ชื่อ"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"คำอธิบายโดยละเอียด"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"ชื่อข้อบกพร่อง"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"สรุปข้อบกพร่อง"</string>
+ <string name="save" msgid="4781509040564835759">"บันทึก"</string>
</resources>
diff --git a/packages/Shell/res/values-tl/strings.xml b/packages/Shell/res/values-tl/strings.xml
index 432eb90..d270401 100644
--- a/packages/Shell/res/values-tl/strings.xml
+++ b/packages/Shell/res/values-tl/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Hindi makunan ng screenshot."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Mga detalye ng ulat ng bug na <xliff:g id="ID">#%d</xliff:g>"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"Filename"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"Pamagat"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"Detalyadong paglalarawan"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"Pamagat ng bug"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"Buod ng bug"</string>
+ <string name="save" msgid="4781509040564835759">"I-save"</string>
</resources>
diff --git a/packages/Shell/res/values-tr/strings.xml b/packages/Shell/res/values-tr/strings.xml
index dae377f..6da3490 100644
--- a/packages/Shell/res/values-tr/strings.xml
+++ b/packages/Shell/res/values-tr/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Ekran görüntüsü alınamadı."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Hata raporu (<xliff:g id="ID">#%d</xliff:g>) ayrıntıları"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"Dosya adı"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"Başlık"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"Ayrıntılı açıklama"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"Hata başlığı"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"Hata özeti"</string>
+ <string name="save" msgid="4781509040564835759">"Kaydet"</string>
</resources>
diff --git a/packages/Shell/res/values-uk/strings.xml b/packages/Shell/res/values-uk/strings.xml
index 02eeb2f..00a7793 100644
--- a/packages/Shell/res/values-uk/strings.xml
+++ b/packages/Shell/res/values-uk/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Не вдалося зробити знімок екрана."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Деталі повідомлення про помилку <xliff:g id="ID">#%d</xliff:g>"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"Назва файлу"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"Назва"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"Детальний опис"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"Назва помилки"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"Опис помилки"</string>
+ <string name="save" msgid="4781509040564835759">"Зберегти"</string>
</resources>
diff --git a/packages/Shell/res/values-ur-rPK/strings.xml b/packages/Shell/res/values-ur-rPK/strings.xml
index 23cada6..abf6940 100644
--- a/packages/Shell/res/values-ur-rPK/strings.xml
+++ b/packages/Shell/res/values-ur-rPK/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"سکرین شاٹ نہیں لیا جا سکا۔"</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"بگ رپورٹ <xliff:g id="ID">#%d</xliff:g> کی تفصیلات"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"فائل کا نام"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"عنوان"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"تفصیلی وضاحت"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"بَگ کا عنوان"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"بَگ کا خلاصہ"</string>
+ <string name="save" msgid="4781509040564835759">"محفوظ کریں"</string>
</resources>
diff --git a/packages/Shell/res/values-uz-rUZ/strings.xml b/packages/Shell/res/values-uz-rUZ/strings.xml
index 39703a2..7782b42 100644
--- a/packages/Shell/res/values-uz-rUZ/strings.xml
+++ b/packages/Shell/res/values-uz-rUZ/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Skrinshot olib bo‘lmadi."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Xatoliklar hisoboti (<xliff:g id="ID">#%d</xliff:g>) tafsilotlari"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"Fayl nomi"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"Nomi"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"Batafsil ta’rif"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"Xatolik nomi"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"Xatolik ta’rifi"</string>
+ <string name="save" msgid="4781509040564835759">"Saqlash"</string>
</resources>
diff --git a/packages/Shell/res/values-vi/strings.xml b/packages/Shell/res/values-vi/strings.xml
index 16ffaff..27a9c7f 100644
--- a/packages/Shell/res/values-vi/strings.xml
+++ b/packages/Shell/res/values-vi/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Không thể chụp ảnh màn hình."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Chi tiết báo cáo lỗi <xliff:g id="ID">#%d</xliff:g>"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"Tên tệp"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"Tiêu đề"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"Mô tả chi tiết"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"Tiêu đề lỗi"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"Tóm tắt lỗi"</string>
+ <string name="save" msgid="4781509040564835759">"Lưu"</string>
</resources>
diff --git a/packages/Shell/res/values-zh-rCN/strings.xml b/packages/Shell/res/values-zh-rCN/strings.xml
index 382478e..65cfbbc 100644
--- a/packages/Shell/res/values-zh-rCN/strings.xml
+++ b/packages/Shell/res/values-zh-rCN/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"无法截图。"</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"错误报告 <xliff:g id="ID">#%d</xliff:g> 详情"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"文件名"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"标题"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"详细说明"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"错误标题"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"错误摘要"</string>
+ <string name="save" msgid="4781509040564835759">"保存"</string>
</resources>
diff --git a/packages/Shell/res/values-zh-rHK/strings.xml b/packages/Shell/res/values-zh-rHK/strings.xml
index 04b5e48..34a849e 100644
--- a/packages/Shell/res/values-zh-rHK/strings.xml
+++ b/packages/Shell/res/values-zh-rHK/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"無法擷取螢幕畫面。"</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"錯誤報告 <xliff:g id="ID">#%d</xliff:g> 的詳情"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"檔案名稱"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"標題"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"詳細說明"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"錯誤標題"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"錯誤摘要"</string>
+ <string name="save" msgid="4781509040564835759">"儲存"</string>
</resources>
diff --git a/packages/Shell/res/values-zh-rTW/strings.xml b/packages/Shell/res/values-zh-rTW/strings.xml
index 7a1ab77..fff73bb 100644
--- a/packages/Shell/res/values-zh-rTW/strings.xml
+++ b/packages/Shell/res/values-zh-rTW/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"無法拍攝螢幕擷取畫面。"</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"錯誤報告 <xliff:g id="ID">#%d</xliff:g> 的詳細資料"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"檔案名稱"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"標題"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"詳細說明"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"錯誤標題"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"錯誤摘要"</string>
+ <string name="save" msgid="4781509040564835759">"儲存"</string>
</resources>
diff --git a/packages/Shell/res/values-zu/strings.xml b/packages/Shell/res/values-zu/strings.xml
index 29b7dd83..868de3e 100644
--- a/packages/Shell/res/values-zu/strings.xml
+++ b/packages/Shell/res/values-zu/strings.xml
@@ -34,6 +34,7 @@
<string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Isithombe-skrini asikwazanga ukuthathwa."</string>
<string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Imininingwane yombiko wesiphazamisi ongu-<xliff:g id="ID">#%d</xliff:g>"</string>
<string name="bugreport_info_name" msgid="4414036021935139527">"Igama lefayela"</string>
- <string name="bugreport_info_title" msgid="5599558206004371052">"Isihloko"</string>
- <string name="bugreport_info_description" msgid="4117088998733546784">"Incazelo enemininingwane"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"Isihloko sesiphazamisi"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"Isifinyezo sesiphazamisi"</string>
+ <string name="save" msgid="4781509040564835759">"Londoloza"</string>
</resources>
diff --git a/packages/Shell/src/com/android/shell/BugreportStorageProvider.java b/packages/Shell/src/com/android/shell/BugreportStorageProvider.java
index 814aa8c..49759c5 100644
--- a/packages/Shell/src/com/android/shell/BugreportStorageProvider.java
+++ b/packages/Shell/src/com/android/shell/BugreportStorageProvider.java
@@ -56,7 +56,7 @@
final MatrixCursor result = new MatrixCursor(resolveRootProjection(projection));
final RowBuilder row = result.newRow();
row.add(Root.COLUMN_ROOT_ID, DOC_ID_ROOT);
- row.add(Root.COLUMN_FLAGS, Root.FLAG_LOCAL_ONLY | Root.FLAG_ADVANCED);
+ row.add(Root.COLUMN_FLAGS, Root.FLAG_LOCAL_ONLY);
row.add(Root.COLUMN_ICON, android.R.mipmap.sym_def_app_icon);
row.add(Root.COLUMN_TITLE, getContext().getString(R.string.bugreport_storage_title));
row.add(Root.COLUMN_DOCUMENT_ID, DOC_ID_ROOT);
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index b5b7bcd..637551c 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -245,7 +245,7 @@
android:stateNotNeeded="true"
android:resumeWhilePausing="true"
android:screenOrientation="behind"
- android:theme="@style/RecentsTheme.Wallpaper">
+ android:theme="@style/RecentsTvTheme.Wallpaper">
<intent-filter>
<action android:name="com.android.systemui.recents.TOGGLE_RECENTS" />
</intent-filter>
diff --git a/packages/SystemUI/res/drawable/ic_info.xml b/packages/SystemUI/res/drawable/ic_info.xml
deleted file mode 100644
index 65e7bf5..0000000
--- a/packages/SystemUI/res/drawable/ic_info.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<!--
-Copyright (C) 2014 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.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24.0dp"
- android:height="24.0dp"
- android:viewportWidth="24.0"
- android:viewportHeight="24.0">
- <path
- android:pathData="M12.000000,2.000000C6.500000,2.000000 2.000000,6.500000 2.000000,12.000000s4.500000,10.000000 10.000000,10.000000c5.500000,0.000000 10.000000,-4.500000 10.000000,-10.000000S17.500000,2.000000 12.000000,2.000000zM13.000000,17.000000l-2.000000,0.000000l0.000000,-6.000000l2.000000,0.000000L13.000000,17.000000zM13.000000,9.000000l-2.000000,0.000000L11.000000,7.000000l2.000000,0.000000L13.000000,9.000000z"
- android:fillColor="#FFFFFF"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/qs_btn_borderless_rect.xml b/packages/SystemUI/res/drawable/qs_btn_borderless_rect.xml
new file mode 100644
index 0000000..03bfd1a
--- /dev/null
+++ b/packages/SystemUI/res/drawable/qs_btn_borderless_rect.xml
@@ -0,0 +1,32 @@
+<!--
+ 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.
+-->
+<inset
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:insetTop="4dp"
+ android:insetBottom="4dp">
+ <ripple
+ android:color="?android:attr/colorControlHighlight" >
+
+ <item android:id="@android:id/mask">
+ <shape>
+ <corners android:radius="@dimen/borderless_button_radius" />
+
+ <solid android:color="@android:color/white" />
+ </shape>
+ </item>
+
+ </ripple>
+</inset>
diff --git a/packages/SystemUI/res/drawable/recents_tv_background_gradient.xml b/packages/SystemUI/res/drawable/recents_tv_background_gradient.xml
new file mode 100644
index 0000000..e98d43f
--- /dev/null
+++ b/packages/SystemUI/res/drawable/recents_tv_background_gradient.xml
@@ -0,0 +1,22 @@
+<?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.
+-->
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="rectangle">
+ <gradient
+ android:startColor="#99000000"
+ android:endColor="#E6000000"
+ android:angle="90"/>
+</shape>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/qs_tile_label.xml b/packages/SystemUI/res/layout/qs_tile_label.xml
index 603ebbf..b0dca9a 100644
--- a/packages/SystemUI/res/layout/qs_tile_label.xml
+++ b/packages/SystemUI/res/layout/qs_tile_label.xml
@@ -20,22 +20,22 @@
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView android:id="@+id/tile_label"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:textColor="@color/qs_tile_text"
- android:gravity="center_horizontal"
- android:minLines="2"
- android:padding="0dp"
- android:fontFamily="sans-serif-condensed"
- android:textStyle="normal"
- android:textSize="@dimen/qs_tile_text_size"
- android:clickable="false" />
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textColor="@color/qs_tile_text"
+ android:gravity="center_horizontal"
+ android:minLines="2"
+ android:padding="0dp"
+ android:fontFamily="sans-serif-condensed"
+ android:textStyle="normal"
+ android:textSize="@dimen/qs_tile_text_size"
+ android:clickable="false" />
<ImageView android:id="@+id/restricted_padlock"
- android:layout_width="@dimen/qs_tile_text_size"
- android:layout_height="@dimen/qs_tile_text_size"
- android:src="@drawable/ic_settings_lock_outline"
- android:layout_marginLeft="@dimen/restricted_padlock_pading"
- android:baselineAlignBottom="true"
- android:scaleType="centerInside"
- android:visibility="gone" />
+ android:layout_width="@dimen/qs_tile_text_size"
+ android:layout_height="match_parent"
+ android:paddingBottom="@dimen/qs_tile_text_size"
+ android:src="@drawable/ic_info"
+ android:layout_marginLeft="@dimen/restricted_padlock_pading"
+ android:scaleType="centerInside"
+ android:visibility="gone" />
</LinearLayout>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/qs_user_detail_item.xml b/packages/SystemUI/res/layout/qs_user_detail_item.xml
index a22c360..661d74a 100644
--- a/packages/SystemUI/res/layout/qs_user_detail_item.xml
+++ b/packages/SystemUI/res/layout/qs_user_detail_item.xml
@@ -53,10 +53,10 @@
<ImageView
android:id="@+id/restricted_padlock"
android:layout_width="@dimen/qs_detail_item_secondary_text_size"
- android:layout_height="@dimen/qs_detail_item_secondary_text_size"
- android:src="@drawable/ic_settings_lock_outline"
+ android:layout_height="match_parent"
+ android:gravity="center_vertical"
+ android:src="@drawable/ic_info"
android:layout_marginLeft="@dimen/restricted_padlock_pading"
- android:baselineAlignBottom="true"
android:scaleType="centerInside"
android:visibility="gone" />
</LinearLayout>
diff --git a/packages/SystemUI/res/layout/recents_on_tv.xml b/packages/SystemUI/res/layout/recents_on_tv.xml
index 94b099e..3a7c1d1 100644
--- a/packages/SystemUI/res/layout/recents_on_tv.xml
+++ b/packages/SystemUI/res/layout/recents_on_tv.xml
@@ -18,9 +18,10 @@
android:id="@+id/recents_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
+ android:background="@drawable/recents_tv_background_gradient"
android:clipChildren="false"
- android:clipToPadding="false" >
-
+ android:clipToPadding="false"
+ android:layoutDirection="rtl">
<com.android.systemui.recents.tv.views.TaskStackHorizontalGridView
android:id="@+id/task_list"
android:layout_width="wrap_content"
diff --git a/packages/SystemUI/res/layout/recents_task_card_view.xml b/packages/SystemUI/res/layout/recents_tv_task_card_view.xml
similarity index 65%
rename from packages/SystemUI/res/layout/recents_task_card_view.xml
rename to packages/SystemUI/res/layout/recents_tv_task_card_view.xml
index fa1daad..c5b1a7a 100644
--- a/packages/SystemUI/res/layout/recents_task_card_view.xml
+++ b/packages/SystemUI/res/layout/recents_tv_task_card_view.xml
@@ -20,28 +20,28 @@
android:focusable="true"
android:focusableInTouchMode="true"
android:layout_gravity="center"
- android:layout_centerInParent="true">
+ android:layout_centerInParent="true"
+ android:layoutDirection="ltr">
- <RelativeLayout
+ <LinearLayout
android:layout_width="@dimen/recents_tv_card_width"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
- android:layout_gravity="center">
- <ImageView
- android:id="@+id/card_view_thumbnail"
- android:layout_width="match_parent"
- android:layout_height="@dimen/recents_tv_card_height"
- android:scaleType="centerCrop"
- android:gravity="center"
- android:layout_alignParentTop="true"
- android:layout_centerHorizontal="true"/>
-
- <RelativeLayout
+ android:layout_gravity="center"
+ android:orientation="vertical" >
+ <LinearLayout
android:id="@+id/card_info_field"
android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_below="@id/card_view_thumbnail"
- android:background="@color/recents_tv_card_background_color" >
+ android:layout_height="wrap_content">
+ <ImageView
+ android:id="@+id/card_extra_badge"
+ android:layout_width="@dimen/recents_tv_card_extra_badge_size"
+ android:layout_height="@dimen/recents_tv_card_extra_badge_size"
+ android:layout_marginBottom="@dimen/recents_tv_icon_padding_bottom"
+ android:layout_marginEnd="@dimen/recents_tv_icon_padding_end"
+ android:scaleType="fitCenter"
+ android:layout_centerVertical="true"
+ android:layout_alignParentRight="true" />
<TextView
android:id="@+id/card_title_text"
android:layout_width="match_parent"
@@ -49,29 +49,21 @@
android:layout_alignParentTop="false"
android:includeFontPadding="true"
android:minLines="1"
- android:maxLines="2"
+ android:maxLines="1"
android:textColor="@color/recents_tv_card_title_text_color"
- android:ellipsize="end" />
- <TextView
- android:id="@+id/card_content_text"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_alignParentStart="true"
- android:layout_below="@id/card_title_text"
- android:includeFontPadding="true"
- android:minLines="1"
- android:maxLines="2"
- android:textColor="@color/recents_tv_card_content_text_color"
- android:ellipsize="end" />
- <ImageView
- android:id="@+id/card_extra_badge"
- android:layout_width="@dimen/recents_tv_card_extra_badge_size"
- android:layout_height="@dimen/recents_tv_card_extra_badge_size"
- android:scaleType="fitCenter"
- android:background="@android:color/transparent"
- android:contentDescription="@null"
- android:layout_centerVertical="true"
- android:layout_alignParentRight="true"/>
- </RelativeLayout>
- </RelativeLayout>
+ android:fontFamily="@string/font_roboto_regular"
+ android:textSize="@dimen/recents_tv_title_text_size"
+ android:layout_marginBottom="@dimen/recents_tv_text_padding_bottom"
+ android:ellipsize="end"/>
+ </LinearLayout>
+ <ImageView
+ android:id="@+id/card_view_thumbnail"
+ android:layout_width="match_parent"
+ android:layout_height="@dimen/recents_tv_card_height"
+ android:scaleType="centerCrop"
+ android:gravity="center"
+ android:layout_alignParentTop="true"
+ android:layout_centerHorizontal="true"
+ android:layout_below="@id/card_title_text" />
+ </LinearLayout>
</com.android.systemui.recents.tv.views.TaskCardView>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/remote_input.xml b/packages/SystemUI/res/layout/remote_input.xml
index 818df3b..75195c4 100644
--- a/packages/SystemUI/res/layout/remote_input.xml
+++ b/packages/SystemUI/res/layout/remote_input.xml
@@ -43,7 +43,7 @@
android:singleLine="true"
android:ellipsize="start"
android:inputType="textShortMessage|textAutoCorrect|textCapSentences"
- android:imeOptions="actionSend" />
+ android:imeOptions="actionSend|flagNoExtractUi" />
<FrameLayout
android:layout_width="wrap_content"
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index 61d4f14..30d9ed7 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -207,8 +207,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Meer tyd."</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Minder tyd."</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Flitslig af."</string>
- <!-- no translation found for accessibility_quick_settings_flashlight_unavailable (8012811023312280810) -->
- <skip />
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Flitslig is nie beskikbaar nie."</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Flitslig aan."</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Flitslig afgeskakel."</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Flitslig aangeskakel."</string>
@@ -456,34 +455,23 @@
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Skakel Bluetooth aan?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Jy moet Bluetooth aanskakel om jou sleutelbord aan jou tablet te koppel."</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Skakel aan"</string>
- <!-- no translation found for show_silently (6841966539811264192) -->
- <skip />
- <!-- no translation found for block (2734508760962682611) -->
- <skip />
- <!-- no translation found for do_not_silence (6878060322594892441) -->
- <skip />
- <!-- no translation found for do_not_silence_block (4070647971382232311) -->
- <skip />
- <!-- no translation found for tuner_full_importance_settings (8103289238676424226) -->
- <skip />
+ <string name="show_silently" msgid="6841966539811264192">"Wys kennisgewings sonder klank"</string>
+ <string name="block" msgid="2734508760962682611">"Blokkeer alle kennisgewings"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"Moenie stilmaak nie"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"Moenie stilmaak of blokkeer nie"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Wys volledige belangrikheidinstellings"</string>
<string name="blocked_importance" msgid="5198578988978234161">"Geblokkeer"</string>
- <!-- no translation found for min_importance (1901894910809414782) -->
- <skip />
+ <string name="min_importance" msgid="1901894910809414782">"Onbelangrik"</string>
<string name="low_importance" msgid="4109929986107147930">"Min belang"</string>
<string name="default_importance" msgid="8192107689995742653">"Normale belang"</string>
<string name="high_importance" msgid="1527066195614050263">"Groot belang"</string>
<string name="max_importance" msgid="5089005872719563894">"Dringende belang"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"Moet nooit hierdie kennisgewings wys nie"</string>
- <!-- no translation found for notification_importance_min (1938190340516905748) -->
- <skip />
- <!-- no translation found for notification_importance_low (3657252049508213048) -->
- <skip />
- <!-- no translation found for notification_importance_default (4466466472622442175) -->
- <skip />
- <!-- no translation found for notification_importance_high (2135428926525093825) -->
- <skip />
- <!-- no translation found for notification_importance_max (5806278962376556491) -->
- <skip />
+ <string name="notification_importance_min" msgid="1938190340516905748">"Wys sonder klank aan die onderkant van die kennisgewinglys"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"Wys hierdie kennisgewings sonder klank"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"Laat hierdie kennisgewing toe om geluide te maak"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"Verskyn vlugtig op die skerm en laat klank toe"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"Wys boaan die kennisgewingslys, verskyn vlugtig op die skerm en laat klank toe"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Meer instellings"</string>
<string name="notification_done" msgid="5279426047273930175">"Klaar"</string>
<string name="color_and_appearance" msgid="1254323855964993144">"Kleur en voorkoms"</string>
@@ -556,8 +544,7 @@
<item msgid="2139628951880142927">"Wys persentasie wanneer gelaai word (verstek)"</item>
<item msgid="3327323682209964956">"Moenie hierdie ikoon wys nie"</item>
</string-array>
- <!-- no translation found for other (4060683095962566764) -->
- <skip />
+ <string name="other" msgid="4060683095962566764">"Ander"</string>
<string name="accessibility_divider" msgid="5903423481953635044">"Skermverdeler"</string>
<string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Skuif af"</string>
<string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Skuif op"</string>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index 6d70c8a..9692ae8 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -207,8 +207,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"ተጨማሪ ጊዜ።"</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"ያነሰ ጊዜ።"</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"የባትሪ ብርሃን ጠፍቷል።"</string>
- <!-- no translation found for accessibility_quick_settings_flashlight_unavailable (8012811023312280810) -->
- <skip />
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"የባትሪ ብርሃን አይገኝም።"</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"የባትሪ ብርሃን በርቷል።"</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"የባትሪ ብርሃን ጠፍቷል።"</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"የባትሪ ብርሃን በርቷል።"</string>
@@ -456,34 +455,23 @@
<string name="enable_bluetooth_title" msgid="5027037706500635269">"ብሉቱዝ ይብራ?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"የቁልፍ ሰሌዳዎን ከእርስዎ ጡባዊ ጋር ለማገናኘት በመጀመሪያ ብሉቱዝን ማብራት አለብዎት።"</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"አብራ"</string>
- <!-- no translation found for show_silently (6841966539811264192) -->
- <skip />
- <!-- no translation found for block (2734508760962682611) -->
- <skip />
- <!-- no translation found for do_not_silence (6878060322594892441) -->
- <skip />
- <!-- no translation found for do_not_silence_block (4070647971382232311) -->
- <skip />
- <!-- no translation found for tuner_full_importance_settings (8103289238676424226) -->
- <skip />
+ <string name="show_silently" msgid="6841966539811264192">"ማሳወቂያዎችን በጸጥታ አሳይ"</string>
+ <string name="block" msgid="2734508760962682611">"ሁሉንም ማሳወቂያዎች አግድ"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"ድምፅ አትዝጋ"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"ድምፅ አትዝጋ ወይም አታግድ"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"ሙሉ የአስፈላጊነት ቅንብሮችን አሳይ"</string>
<string name="blocked_importance" msgid="5198578988978234161">"የታገዱ"</string>
- <!-- no translation found for min_importance (1901894910809414782) -->
- <skip />
+ <string name="min_importance" msgid="1901894910809414782">"አነስተኛ አስፈላጊነት"</string>
<string name="low_importance" msgid="4109929986107147930">"ዝቅተኛ አስፈላጊነት"</string>
<string name="default_importance" msgid="8192107689995742653">"መደበኛ አስፈላጊነት"</string>
<string name="high_importance" msgid="1527066195614050263">"ከፍተኛ አስፈላጊነት"</string>
<string name="max_importance" msgid="5089005872719563894">"አስቸኳይ አስፈላጊነት"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"እነዚህን ማሳወቂያዎች በጭራሽ አታሳይ"</string>
- <!-- no translation found for notification_importance_min (1938190340516905748) -->
- <skip />
- <!-- no translation found for notification_importance_low (3657252049508213048) -->
- <skip />
- <!-- no translation found for notification_importance_default (4466466472622442175) -->
- <skip />
- <!-- no translation found for notification_importance_high (2135428926525093825) -->
- <skip />
- <!-- no translation found for notification_importance_max (5806278962376556491) -->
- <skip />
+ <string name="notification_importance_min" msgid="1938190340516905748">"በማሳወቂያ ዝርዝሩ ታችኛውን ክፍል ላይ በጸጥታ አሳይ"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"እነዚህን ማሳወቂያዎች በጸጥታ አሳይ"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"እነዚህ ማሳወቂያዎች ድምፆችን እንዲፈጥሩ ፍቀድ"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"ወደ ማያ ገጹ አስገባና ድምፅ ፍቀድ"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"በማሳወቂያዎች ዝርዝር አናት ላይ አሳይ፣ ወደ ማያ ገጹ አሳይና ድምፅ ፍቀድ"</string>
<string name="notification_more_settings" msgid="816306283396553571">"ተጨማሪ ቅንብሮች"</string>
<string name="notification_done" msgid="5279426047273930175">"ተከናውኗል"</string>
<string name="color_and_appearance" msgid="1254323855964993144">"ቀለም እና መልክ"</string>
@@ -556,8 +544,7 @@
<item msgid="2139628951880142927">"የባትሪ ኃይል በሚሞላበት ጊዜ መቶኛ አሳይ (ነባሪ)"</item>
<item msgid="3327323682209964956">"ይህን አዶ አታሳይ"</item>
</string-array>
- <!-- no translation found for other (4060683095962566764) -->
- <skip />
+ <string name="other" msgid="4060683095962566764">"ሌላ"</string>
<string name="accessibility_divider" msgid="5903423481953635044">"የተከፈለ የማያ ገጽ ከፋይ"</string>
<string name="accessibility_action_divider_move_down" msgid="704893304141890042">"ወደ ታች ሂድ"</string>
<string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"ወደ ላይ ሂድ"</string>
diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
index 2e4724b..3edc805 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
@@ -208,8 +208,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Više vremena."</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Manje vremena."</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Baterijska lampa je isključena."</string>
- <!-- no translation found for accessibility_quick_settings_flashlight_unavailable (8012811023312280810) -->
- <skip />
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Lampa nije dostupna."</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Baterijska lampa je uključena."</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Baterijska lampa je isključena."</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Baterijska lampa je uključena."</string>
@@ -457,34 +456,23 @@
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Želite li da uključite Bluetooth?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Da biste povezali tastaturu sa tabletom, prvo morate da uključite Bluetooth."</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Uključi"</string>
- <!-- no translation found for show_silently (6841966539811264192) -->
- <skip />
- <!-- no translation found for block (2734508760962682611) -->
- <skip />
- <!-- no translation found for do_not_silence (6878060322594892441) -->
- <skip />
- <!-- no translation found for do_not_silence_block (4070647971382232311) -->
- <skip />
- <!-- no translation found for tuner_full_importance_settings (8103289238676424226) -->
- <skip />
+ <string name="show_silently" msgid="6841966539811264192">"Prikazuj obaveštenja bez zvuka"</string>
+ <string name="block" msgid="2734508760962682611">"Blokiraj sva obaveštenja"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"Ne isključuj zvuk"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"Ne isključuju zvuk niti blokiraj"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Prikaži kompletna podešavanja važnosti"</string>
<string name="blocked_importance" msgid="5198578988978234161">"Blokirana"</string>
- <!-- no translation found for min_importance (1901894910809414782) -->
- <skip />
+ <string name="min_importance" msgid="1901894910809414782">"Veoma mala važnost"</string>
<string name="low_importance" msgid="4109929986107147930">"Mala važnost"</string>
<string name="default_importance" msgid="8192107689995742653">"Uobičajena važnost"</string>
<string name="high_importance" msgid="1527066195614050263">"Velika važnost"</string>
<string name="max_importance" msgid="5089005872719563894">"Važnost: hitno"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"Ova obaveštenja se nikada ne prikazuju"</string>
- <!-- no translation found for notification_importance_min (1938190340516905748) -->
- <skip />
- <!-- no translation found for notification_importance_low (3657252049508213048) -->
- <skip />
- <!-- no translation found for notification_importance_default (4466466472622442175) -->
- <skip />
- <!-- no translation found for notification_importance_high (2135428926525093825) -->
- <skip />
- <!-- no translation found for notification_importance_max (5806278962376556491) -->
- <skip />
+ <string name="notification_importance_min" msgid="1938190340516905748">"Prikazuju se u dnu liste obaveštenja bez zvuka"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"Ova obaveštenja se prikazuju bez zvuka"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"Dozvolite da ova obaveštenja emituju zvuk"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"Nakratko se prikazuju na ekranu i emituju zvuk"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"Prikazuju se u vrhu liste obaveštenja, nakratko se prikazuju na ekranu i emituju zvuk"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Još podešavanja"</string>
<string name="notification_done" msgid="5279426047273930175">"Gotovo"</string>
<string name="color_and_appearance" msgid="1254323855964993144">"Boja i izgled"</string>
@@ -557,8 +545,7 @@
<item msgid="2139628951880142927">"Prikaži procenat tokom punjenja (podrazumevano)"</item>
<item msgid="3327323682209964956">"Ne prikazuj ovu ikonu"</item>
</string-array>
- <!-- no translation found for other (4060683095962566764) -->
- <skip />
+ <string name="other" msgid="4060683095962566764">"Drugo"</string>
<string name="accessibility_divider" msgid="5903423481953635044">"Razdelnik podeljenog ekrana"</string>
<string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Pomeri nadole"</string>
<string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Pomeri nagore"</string>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index c97a6a5..84757b7 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -207,8 +207,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Повече време."</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"По-малко време."</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Фенерчето е изключено."</string>
- <!-- no translation found for accessibility_quick_settings_flashlight_unavailable (8012811023312280810) -->
- <skip />
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Няма достъп до фенерчето."</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Фенерчето е включено."</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Фенерчето е изключено."</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Фенерчето е включено."</string>
@@ -456,34 +455,23 @@
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Да се включи ли Bluetooth?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"За да свържете клавиатурата с таблета си, първо трябва да включите Bluetooth."</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Включване"</string>
- <!-- no translation found for show_silently (6841966539811264192) -->
- <skip />
- <!-- no translation found for block (2734508760962682611) -->
- <skip />
- <!-- no translation found for do_not_silence (6878060322594892441) -->
- <skip />
- <!-- no translation found for do_not_silence_block (4070647971382232311) -->
- <skip />
- <!-- no translation found for tuner_full_importance_settings (8103289238676424226) -->
- <skip />
+ <string name="show_silently" msgid="6841966539811264192">"Показване на известията без звуков сигнал"</string>
+ <string name="block" msgid="2734508760962682611">"Блокиране на всички известия"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"Без заглушаване на звуковите сигнали"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"Без заглушаване на звуковите сигнали или блокиране"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Показване на пълните настройки за важността"</string>
<string name="blocked_importance" msgid="5198578988978234161">"Блокирано"</string>
- <!-- no translation found for min_importance (1901894910809414782) -->
- <skip />
+ <string name="min_importance" msgid="1901894910809414782">"Минимална важност"</string>
<string name="low_importance" msgid="4109929986107147930">"Малка важност"</string>
<string name="default_importance" msgid="8192107689995742653">"Нормална важност"</string>
<string name="high_importance" msgid="1527066195614050263">"Голяма важност"</string>
<string name="max_importance" msgid="5089005872719563894">"Неотложна важност"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"Тези известия не се показват"</string>
- <!-- no translation found for notification_importance_min (1938190340516905748) -->
- <skip />
- <!-- no translation found for notification_importance_low (3657252049508213048) -->
- <skip />
- <!-- no translation found for notification_importance_default (4466466472622442175) -->
- <skip />
- <!-- no translation found for notification_importance_high (2135428926525093825) -->
- <skip />
- <!-- no translation found for notification_importance_max (5806278962376556491) -->
- <skip />
+ <string name="notification_importance_min" msgid="1938190340516905748">"Показване без звуков сигнал най-долу в списъка с известия"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"Показване на тези известия без звуков сигнал"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"Разрешаване при тези известия да се издава звуков сигнал"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"Показване на екрана и разрешаване на звуков сигнал"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"Показване най-горе в списъка с известия, както и на екрана и разрешаване на звуков сигнал"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Още настройки"</string>
<string name="notification_done" msgid="5279426047273930175">"Готово"</string>
<string name="color_and_appearance" msgid="1254323855964993144">"Цвят и облик"</string>
@@ -556,8 +544,7 @@
<item msgid="2139628951880142927">"Процентът да се показва при зареждане (по подразбиране)"</item>
<item msgid="3327323682209964956">"Тази икона да не се показва"</item>
</string-array>
- <!-- no translation found for other (4060683095962566764) -->
- <skip />
+ <string name="other" msgid="4060683095962566764">"Друго"</string>
<string name="accessibility_divider" msgid="5903423481953635044">"Разделител в режима за разделен екран"</string>
<string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Преместване надолу"</string>
<string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Преместване нагоре"</string>
diff --git a/packages/SystemUI/res/values-bn-rBD/strings.xml b/packages/SystemUI/res/values-bn-rBD/strings.xml
index f59f3ca..18f37e6 100644
--- a/packages/SystemUI/res/values-bn-rBD/strings.xml
+++ b/packages/SystemUI/res/values-bn-rBD/strings.xml
@@ -548,6 +548,6 @@
<string name="accessibility_divider" msgid="5903423481953635044">"বিভক্ত-স্ক্রীন বিভাজক"</string>
<string name="accessibility_action_divider_move_down" msgid="704893304141890042">"নীচে সরান"</string>
<string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"উপরে সরান"</string>
- <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"বামে সরান"</string>
+ <string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"বাঁয়ে সরান"</string>
<string name="accessibility_action_divider_move_right" msgid="4671522715182567972">"ডানে সরান"</string>
</resources>
diff --git a/packages/SystemUI/res/values-bs-rBA/strings.xml b/packages/SystemUI/res/values-bs-rBA/strings.xml
index 865b1ad..5666c5f 100644
--- a/packages/SystemUI/res/values-bs-rBA/strings.xml
+++ b/packages/SystemUI/res/values-bs-rBA/strings.xml
@@ -208,8 +208,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Više vremena."</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Manje vremena."</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Svjetiljka isključena."</string>
- <!-- no translation found for accessibility_quick_settings_flashlight_unavailable (8012811023312280810) -->
- <skip />
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Svjetiljka nije dostupna."</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Svjetiljka uključena."</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Svjetiljka je isključena."</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Svjetiljka je uključena."</string>
@@ -457,34 +456,23 @@
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Želiti li uključiti Bluetooth?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Da povežete tastaturu sa tabletom, prvo morate uključiti Bluetooth."</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Uključi"</string>
- <!-- no translation found for show_silently (6841966539811264192) -->
- <skip />
- <!-- no translation found for block (2734508760962682611) -->
- <skip />
- <!-- no translation found for do_not_silence (6878060322594892441) -->
- <skip />
- <!-- no translation found for do_not_silence_block (4070647971382232311) -->
- <skip />
- <!-- no translation found for tuner_full_importance_settings (8103289238676424226) -->
- <skip />
+ <string name="show_silently" msgid="6841966539811264192">"Nečujno pokaži obavijesti"</string>
+ <string name="block" msgid="2734508760962682611">"Blokiraj sva obavještenja"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"Nemoj utišati"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"Nemoj utišati ili blokirati"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Pokaži kompletne postavke za određivanje značaja"</string>
<string name="blocked_importance" msgid="5198578988978234161">"Blokirano"</string>
- <!-- no translation found for min_importance (1901894910809414782) -->
- <skip />
+ <string name="min_importance" msgid="1901894910809414782">"Minimalni značaj"</string>
<string name="low_importance" msgid="4109929986107147930">"Mali značaj"</string>
<string name="default_importance" msgid="8192107689995742653">"Normalan značaj"</string>
<string name="high_importance" msgid="1527066195614050263">"Visok značaj"</string>
<string name="max_importance" msgid="5089005872719563894">"Hitan značaj"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"Nikada ne prikazuj ova obavještenja"</string>
- <!-- no translation found for notification_importance_min (1938190340516905748) -->
- <skip />
- <!-- no translation found for notification_importance_low (3657252049508213048) -->
- <skip />
- <!-- no translation found for notification_importance_default (4466466472622442175) -->
- <skip />
- <!-- no translation found for notification_importance_high (2135428926525093825) -->
- <skip />
- <!-- no translation found for notification_importance_max (5806278962376556491) -->
- <skip />
+ <string name="notification_importance_min" msgid="1938190340516905748">"Nečujno pokaži na dnu spiska obavještenja"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"Nečujno prikaži ova obavještenja"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"Dozvolite zvuk na ovim obavještenjima"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"Kratko prikaži na ekranu i dozvoli zvuk i dozvoli zvuk"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"Pokaži na vrhu liste obaveštenja, kratko prikaži na ekranu i dozvoli zvuk"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Više postavki"</string>
<string name="notification_done" msgid="5279426047273930175">"Gotovo"</string>
<string name="color_and_appearance" msgid="1254323855964993144">"Boja i izgled"</string>
@@ -557,8 +545,7 @@
<item msgid="2139628951880142927">"Pokaži postotak u toku punjenja (zadano)"</item>
<item msgid="3327323682209964956">"Ne prikazuj ovu ikonu"</item>
</string-array>
- <!-- no translation found for other (4060683095962566764) -->
- <skip />
+ <string name="other" msgid="4060683095962566764">"Ostalo"</string>
<string name="accessibility_divider" msgid="5903423481953635044">"Razdjelnik ekrana"</string>
<string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Pomjeri dolje"</string>
<string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Pomjeri gore"</string>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index 3243f74..3747be0 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -207,8 +207,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Més temps"</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Menys temps"</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Llanterna desactivada"</string>
- <!-- no translation found for accessibility_quick_settings_flashlight_unavailable (8012811023312280810) -->
- <skip />
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"La llanterna no està disponible."</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Llanterna activada"</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Llanterna desactivada."</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Llanterna activada."</string>
@@ -456,34 +455,23 @@
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Vols activar el Bluetooth?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Per connectar el teclat amb la tauleta, primer has d\'activar el Bluetooth."</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Activa"</string>
- <!-- no translation found for show_silently (6841966539811264192) -->
- <skip />
- <!-- no translation found for block (2734508760962682611) -->
- <skip />
- <!-- no translation found for do_not_silence (6878060322594892441) -->
- <skip />
- <!-- no translation found for do_not_silence_block (4070647971382232311) -->
- <skip />
- <!-- no translation found for tuner_full_importance_settings (8103289238676424226) -->
- <skip />
+ <string name="show_silently" msgid="6841966539811264192">"Mostra les notificacions de manera silenciosa"</string>
+ <string name="block" msgid="2734508760962682611">"Bloqueja totes les notificacions"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"No silenciïs"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"No silenciïs ni bloquegis"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Mostra la configuració de la importància completa"</string>
<string name="blocked_importance" msgid="5198578988978234161">"Bloquejades"</string>
- <!-- no translation found for min_importance (1901894910809414782) -->
- <skip />
+ <string name="min_importance" msgid="1901894910809414782">"Importància mínima"</string>
<string name="low_importance" msgid="4109929986107147930">"Importància baixa"</string>
<string name="default_importance" msgid="8192107689995742653">"Importància normal"</string>
<string name="high_importance" msgid="1527066195614050263">"Importància alta"</string>
<string name="max_importance" msgid="5089005872719563894">"Importància urgent"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"No mostris mai aquestes notificacions"</string>
- <!-- no translation found for notification_importance_min (1938190340516905748) -->
- <skip />
- <!-- no translation found for notification_importance_low (3657252049508213048) -->
- <skip />
- <!-- no translation found for notification_importance_default (4466466472622442175) -->
- <skip />
- <!-- no translation found for notification_importance_high (2135428926525093825) -->
- <skip />
- <!-- no translation found for notification_importance_max (5806278962376556491) -->
- <skip />
+ <string name="notification_importance_min" msgid="1938190340516905748">"Les notificacions es mostren de manera silenciosa al capdavall de la llista"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"Mostra aquestes notificacions de manera silenciosa"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"Permet que aquestes notificacions emetin sons"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"Les notificacions apareixen a la pantalla i poden emetre sons"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"Les notificacions es mostren al capdamunt de la llista, apareixen a la pantalla i poden emetre sons"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Més opcions"</string>
<string name="notification_done" msgid="5279426047273930175">"Fet"</string>
<string name="color_and_appearance" msgid="1254323855964993144">"Color i aparença"</string>
@@ -556,8 +544,7 @@
<item msgid="2139628951880142927">"Mostra el percentatge quan es carregui (opció predeterminada)"</item>
<item msgid="3327323682209964956">"No mostris aquesta icona"</item>
</string-array>
- <!-- no translation found for other (4060683095962566764) -->
- <skip />
+ <string name="other" msgid="4060683095962566764">"Altres"</string>
<string name="accessibility_divider" msgid="5903423481953635044">"Divisor de pantalles"</string>
<string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Mou avall"</string>
<string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Mou amunt"</string>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index b5b4037..48c9c55 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -209,8 +209,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Delší doba"</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Kratší doba"</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Svítilna je vypnutá."</string>
- <!-- no translation found for accessibility_quick_settings_flashlight_unavailable (8012811023312280810) -->
- <skip />
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Svítilna není k dispozici."</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Svítilna je zapnutá."</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Svítilna je vypnutá."</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Svítilna je zapnutá."</string>
@@ -458,34 +457,23 @@
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Zapnout Bluetooth?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Chcete-li klávesnici připojit k tabletu, nejdříve musíte zapnout Bluetooth."</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Zapnout"</string>
- <!-- no translation found for show_silently (6841966539811264192) -->
- <skip />
- <!-- no translation found for block (2734508760962682611) -->
- <skip />
- <!-- no translation found for do_not_silence (6878060322594892441) -->
- <skip />
- <!-- no translation found for do_not_silence_block (4070647971382232311) -->
- <skip />
- <!-- no translation found for tuner_full_importance_settings (8103289238676424226) -->
- <skip />
+ <string name="show_silently" msgid="6841966539811264192">"Zobrazovat oznámení tiše"</string>
+ <string name="block" msgid="2734508760962682611">"Blokovat všechna oznámení"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"Bez ztlumení"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"Bez ztlumení a blokování"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Zobrazit všechna nastavení důležitosti"</string>
<string name="blocked_importance" msgid="5198578988978234161">"Blokováno"</string>
- <!-- no translation found for min_importance (1901894910809414782) -->
- <skip />
+ <string name="min_importance" msgid="1901894910809414782">"Minimální důležitost"</string>
<string name="low_importance" msgid="4109929986107147930">"Nízká důležitost"</string>
<string name="default_importance" msgid="8192107689995742653">"Normální důležitost"</string>
<string name="high_importance" msgid="1527066195614050263">"Vysoká důležitost"</string>
<string name="max_importance" msgid="5089005872719563894">"Urgentní důležitost"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"Tato oznámení nikdy nezobrazovat"</string>
- <!-- no translation found for notification_importance_min (1938190340516905748) -->
- <skip />
- <!-- no translation found for notification_importance_low (3657252049508213048) -->
- <skip />
- <!-- no translation found for notification_importance_default (4466466472622442175) -->
- <skip />
- <!-- no translation found for notification_importance_high (2135428926525093825) -->
- <skip />
- <!-- no translation found for notification_importance_max (5806278962376556491) -->
- <skip />
+ <string name="notification_importance_min" msgid="1938190340516905748">"Tato oznámení zobrazovat na konci seznamu bez zvukového upozornění"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"Tato oznámení zobrazovat bez zvukového upozornění"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"Povolit těmto oznámením vydávat zvuky"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"Tato oznámení zobrazovat přímo na obrazovce a upozornit na ně zvukem"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"Tato oznámení zobrazovat na začátku seznamu, zobrazit přímo na obrazovce a upozornit na ně zvukem"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Další nastavení"</string>
<string name="notification_done" msgid="5279426047273930175">"Hotovo"</string>
<string name="color_and_appearance" msgid="1254323855964993144">"Barva a vzhled"</string>
@@ -558,8 +546,7 @@
<item msgid="2139628951880142927">"Zobrazovat procento při nabíjení (výchozí nastavení)"</item>
<item msgid="3327323682209964956">"Tuto ikonu nezobrazovat"</item>
</string-array>
- <!-- no translation found for other (4060683095962566764) -->
- <skip />
+ <string name="other" msgid="4060683095962566764">"Jiné"</string>
<string name="accessibility_divider" msgid="5903423481953635044">"Čára rozdělující obrazovku"</string>
<string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Přesunout dolů"</string>
<string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Přesunout nahoru"</string>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index f4987d7..50d01ea 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -207,8 +207,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Mere tid."</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Mindre tid."</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Lommelygten er slået fra."</string>
- <!-- no translation found for accessibility_quick_settings_flashlight_unavailable (8012811023312280810) -->
- <skip />
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Lommelygten er ikke tilgængelig."</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Lommelygten er slået til."</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Lommelygten er slået fra."</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Lommelygten er slået til."</string>
@@ -456,34 +455,23 @@
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Vil du slå Bluetooth til?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Bluetooth skal være slået til, før du kan knytte dit tastatur til din tablet."</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Slå til"</string>
- <!-- no translation found for show_silently (6841966539811264192) -->
- <skip />
- <!-- no translation found for block (2734508760962682611) -->
- <skip />
- <!-- no translation found for do_not_silence (6878060322594892441) -->
- <skip />
- <!-- no translation found for do_not_silence_block (4070647971382232311) -->
- <skip />
- <!-- no translation found for tuner_full_importance_settings (8103289238676424226) -->
- <skip />
+ <string name="show_silently" msgid="6841966539811264192">"Vis underretninger lydløst"</string>
+ <string name="block" msgid="2734508760962682611">"Bloker alle underretninger"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"Skal ikke sættes på lydløs"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"Skal ikke sættes på lydløs eller blokeres"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Vis alle indstillinger for vigtighed"</string>
<string name="blocked_importance" msgid="5198578988978234161">"Blokeret"</string>
- <!-- no translation found for min_importance (1901894910809414782) -->
- <skip />
+ <string name="min_importance" msgid="1901894910809414782">"Min vigtighed"</string>
<string name="low_importance" msgid="4109929986107147930">"Lille vigtighed"</string>
<string name="default_importance" msgid="8192107689995742653">"Normal vigtighed"</string>
<string name="high_importance" msgid="1527066195614050263">"Stor vigtighed"</string>
<string name="max_importance" msgid="5089005872719563894">"Presserende vigtighed"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"Vis aldrig disse underretninger"</string>
- <!-- no translation found for notification_importance_min (1938190340516905748) -->
- <skip />
- <!-- no translation found for notification_importance_low (3657252049508213048) -->
- <skip />
- <!-- no translation found for notification_importance_default (4466466472622442175) -->
- <skip />
- <!-- no translation found for notification_importance_high (2135428926525093825) -->
- <skip />
- <!-- no translation found for notification_importance_max (5806278962376556491) -->
- <skip />
+ <string name="notification_importance_min" msgid="1938190340516905748">"Vis lydløst nederst på listen over underretninger"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"Vis disse underretninger lydløst"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"Giv disse underretninger tilladelse til at give lyd"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"Vis på skærmen, og tillad lyd"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"Vis øverst på listen over underretninger, vis på skærmen, og tillad lyd"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Flere indstillinger"</string>
<string name="notification_done" msgid="5279426047273930175">"Færdig"</string>
<string name="color_and_appearance" msgid="1254323855964993144">"Farve og udseende"</string>
@@ -556,8 +544,7 @@
<item msgid="2139628951880142927">"Vis procent ved opladning (standard)"</item>
<item msgid="3327323682209964956">"Vis ikke dette ikon"</item>
</string-array>
- <!-- no translation found for other (4060683095962566764) -->
- <skip />
+ <string name="other" msgid="4060683095962566764">"Andet"</string>
<string name="accessibility_divider" msgid="5903423481953635044">"Adskiller til delt skærm"</string>
<string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Flyt ned"</string>
<string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Flyt op"</string>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index ac0adbb..fd8cf89 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -207,8 +207,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Mehr Zeit"</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Weniger Zeit"</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Taschenlampe deaktiviert"</string>
- <!-- no translation found for accessibility_quick_settings_flashlight_unavailable (8012811023312280810) -->
- <skip />
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Taschenlampe nicht verfügbar."</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Taschenlampe aktiviert"</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Die Taschenlampe ist deaktiviert."</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Die Taschenlampe ist aktiviert."</string>
@@ -456,34 +455,23 @@
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Bluetooth aktivieren?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Zum Verbinden von Tastatur und Tablet muss Bluetooth aktiviert sein."</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Aktivieren"</string>
- <!-- no translation found for show_silently (6841966539811264192) -->
- <skip />
- <!-- no translation found for block (2734508760962682611) -->
- <skip />
- <!-- no translation found for do_not_silence (6878060322594892441) -->
- <skip />
- <!-- no translation found for do_not_silence_block (4070647971382232311) -->
- <skip />
- <!-- no translation found for tuner_full_importance_settings (8103289238676424226) -->
- <skip />
+ <string name="show_silently" msgid="6841966539811264192">"Benachrichtigungen ohne Ton anzeigen"</string>
+ <string name="block" msgid="2734508760962682611">"Alle Benachrichtigungen blockieren"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"Nicht stummschalten"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"Nicht stummschalten oder blockieren"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Vollständige Wichtigkeitseinstellungen anzeigen"</string>
<string name="blocked_importance" msgid="5198578988978234161">"Blockiert"</string>
- <!-- no translation found for min_importance (1901894910809414782) -->
- <skip />
+ <string name="min_importance" msgid="1901894910809414782">"Minimum-Wichtigkeit"</string>
<string name="low_importance" msgid="4109929986107147930">"Geringe Wichtigkeit"</string>
<string name="default_importance" msgid="8192107689995742653">"Reguläre Wichtigkeit"</string>
<string name="high_importance" msgid="1527066195614050263">"Hohe Wichtigkeit"</string>
<string name="max_importance" msgid="5089005872719563894">"Sehr hohe Wichtigkeit"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"Diese Benachrichtigungen niemals anzeigen"</string>
- <!-- no translation found for notification_importance_min (1938190340516905748) -->
- <skip />
- <!-- no translation found for notification_importance_low (3657252049508213048) -->
- <skip />
- <!-- no translation found for notification_importance_default (4466466472622442175) -->
- <skip />
- <!-- no translation found for notification_importance_high (2135428926525093825) -->
- <skip />
- <!-- no translation found for notification_importance_max (5806278962376556491) -->
- <skip />
+ <string name="notification_importance_min" msgid="1938190340516905748">"Ohne Ton am Ende der Benachrichtigungsliste anzeigen"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"Diese Benachrichtigungen ohne Ton anzeigen"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"Für diese Benachrichtigungen Ton zulassen"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"Auf dem Display einblenden und Ton zulassen"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"Ganz oben in der Benachrichtigungsliste anzeigen, auf dem Display einblenden und Ton zulassen"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Weitere Einstellungen"</string>
<string name="notification_done" msgid="5279426047273930175">"Fertig"</string>
<string name="color_and_appearance" msgid="1254323855964993144">"Farbe und Darstellung"</string>
@@ -556,8 +544,7 @@
<item msgid="2139628951880142927">"Prozentwert beim Laden anzeigen (Standardeinstellung)"</item>
<item msgid="3327323682209964956">"Dieses Symbol nicht anzeigen"</item>
</string-array>
- <!-- no translation found for other (4060683095962566764) -->
- <skip />
+ <string name="other" msgid="4060683095962566764">"Sonstiges"</string>
<string name="accessibility_divider" msgid="5903423481953635044">"Bildschirmteiler"</string>
<string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Nach unten verschieben"</string>
<string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Nach oben verschieben"</string>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index 754c92e..b5f55d9 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -207,8 +207,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Περισσότερη ώρα."</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Λιγότερη ώρα."</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Ανενεργός φακός."</string>
- <!-- no translation found for accessibility_quick_settings_flashlight_unavailable (8012811023312280810) -->
- <skip />
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Ο φακός δεν είναι διαθέσιμος."</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Ενεργός φακός."</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Ο φακός απενεργοποιήθηκε."</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Ο φακός ενεργοποιήθηκε."</string>
@@ -456,34 +455,23 @@
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Ενεργοποίηση Bluetooth;"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Για να συνδέσετε το πληκτρολόγιο με το tablet σας, θα πρέπει πρώτα να ενεργοποιήσετε το Bluetooth."</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Ενεργοποίηση"</string>
- <!-- no translation found for show_silently (6841966539811264192) -->
- <skip />
- <!-- no translation found for block (2734508760962682611) -->
- <skip />
- <!-- no translation found for do_not_silence (6878060322594892441) -->
- <skip />
- <!-- no translation found for do_not_silence_block (4070647971382232311) -->
- <skip />
- <!-- no translation found for tuner_full_importance_settings (8103289238676424226) -->
- <skip />
+ <string name="show_silently" msgid="6841966539811264192">"Εμφάνιση ειδοποιήσεων χωρίς ήχο"</string>
+ <string name="block" msgid="2734508760962682611">"Αποκλεισμός όλων των ειδοποιήσεων"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"Χωρίς σίγαση"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"Χωρίς σίγαση ή αποκλεισμό"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Εμφάνιση όλων των ρυθμίσεων βαρύτητας"</string>
<string name="blocked_importance" msgid="5198578988978234161">"Αποκλεισμένες"</string>
- <!-- no translation found for min_importance (1901894910809414782) -->
- <skip />
+ <string name="min_importance" msgid="1901894910809414782">"Ελάχιστη βαρύτητα"</string>
<string name="low_importance" msgid="4109929986107147930">"Μικρής βαρύτητας"</string>
<string name="default_importance" msgid="8192107689995742653">"Κανονικής βαρύτητας"</string>
<string name="high_importance" msgid="1527066195614050263">"Μεγάλης βαρύτητας"</string>
<string name="max_importance" msgid="5089005872719563894">"Επείγουσες"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"Να μην εμφανίζονται ποτέ αυτές οι ειδοποιήσεις"</string>
- <!-- no translation found for notification_importance_min (1938190340516905748) -->
- <skip />
- <!-- no translation found for notification_importance_low (3657252049508213048) -->
- <skip />
- <!-- no translation found for notification_importance_default (4466466472622442175) -->
- <skip />
- <!-- no translation found for notification_importance_high (2135428926525093825) -->
- <skip />
- <!-- no translation found for notification_importance_max (5806278962376556491) -->
- <skip />
+ <string name="notification_importance_min" msgid="1938190340516905748">"Να εμφανίζονται στο κάτω μέρος της λίστας ειδοποιήσεων χωρίς ήχο"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"Να εμφανίζονται αυτές οι ειδοποιήσεις χωρίς ήχο"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"Να επιτρέπονται οι ήχοι από αυτές τις ειδοποιήσεις"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"Να προβάλλονται στην οθόνη και να επιτρέπεται ο ήχος"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"Να εμφανίζονται στην κορυφή της λίστας ειδοποιήσεων, να προβάλλονται στην οθόνη και να επιτρέπεται ο ήχος"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Περισσότερες ρυθμίσεις"</string>
<string name="notification_done" msgid="5279426047273930175">"Τέλος"</string>
<string name="color_and_appearance" msgid="1254323855964993144">"Χρώμα και εμφάνιση"</string>
@@ -556,8 +544,7 @@
<item msgid="2139628951880142927">"Να εμφανίζεται ποσοστό κατά τη φόρτιση (προεπιλογή)"</item>
<item msgid="3327323682209964956">"Να μην εμφανίζεται αυτό το εικονίδιο"</item>
</string-array>
- <!-- no translation found for other (4060683095962566764) -->
- <skip />
+ <string name="other" msgid="4060683095962566764">"Άλλο"</string>
<string name="accessibility_divider" msgid="5903423481953635044">"Διαχωριστικό οθόνης"</string>
<string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Μετακίνηση προς τα κάτω"</string>
<string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Μετακίνηση προς τα επάνω"</string>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index f3c21df..856c1c1 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -207,8 +207,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Más tiempo"</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Menos tiempo"</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Linterna desactivada"</string>
- <!-- no translation found for accessibility_quick_settings_flashlight_unavailable (8012811023312280810) -->
- <skip />
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"La linterna no está disponible."</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Linterna activada"</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Linterna desactivada"</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Linterna activada"</string>
@@ -456,34 +455,23 @@
<string name="enable_bluetooth_title" msgid="5027037706500635269">"¿Activar Bluetooth?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Para conectar el teclado con la tablet, primero debes activar Bluetooth."</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Activar"</string>
- <!-- no translation found for show_silently (6841966539811264192) -->
- <skip />
- <!-- no translation found for block (2734508760962682611) -->
- <skip />
- <!-- no translation found for do_not_silence (6878060322594892441) -->
- <skip />
- <!-- no translation found for do_not_silence_block (4070647971382232311) -->
- <skip />
- <!-- no translation found for tuner_full_importance_settings (8103289238676424226) -->
- <skip />
+ <string name="show_silently" msgid="6841966539811264192">"Mostrar notificaciones de manera silenciosa"</string>
+ <string name="block" msgid="2734508760962682611">"Bloquear todas las notificaciones"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"No silenciar"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"No silenciar ni bloquear"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Mostrar configuración de importancia"</string>
<string name="blocked_importance" msgid="5198578988978234161">"Bloqueada"</string>
- <!-- no translation found for min_importance (1901894910809414782) -->
- <skip />
+ <string name="min_importance" msgid="1901894910809414782">"Importancia mínima"</string>
<string name="low_importance" msgid="4109929986107147930">"Poca importancia"</string>
<string name="default_importance" msgid="8192107689995742653">"Importancia normal"</string>
<string name="high_importance" msgid="1527066195614050263">"Importancia alta"</string>
<string name="max_importance" msgid="5089005872719563894">"Urgente"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"No mostrar nunca estas notificaciones"</string>
- <!-- no translation found for notification_importance_min (1938190340516905748) -->
- <skip />
- <!-- no translation found for notification_importance_low (3657252049508213048) -->
- <skip />
- <!-- no translation found for notification_importance_default (4466466472622442175) -->
- <skip />
- <!-- no translation found for notification_importance_high (2135428926525093825) -->
- <skip />
- <!-- no translation found for notification_importance_max (5806278962376556491) -->
- <skip />
+ <string name="notification_importance_min" msgid="1938190340516905748">"Mostrar en la parte inferior de la lista de notificaciones sin emitir sonido"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"Mostrar estas notificaciones de manera silenciosa"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"Permitir que estas notificaciones emitan sonidos"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"Ver en la pantalla y permitir sonidos"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"Mostrar en la parte superior de la lista de notificaciones, ver en la pantalla y permitir sonidos"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Más opciones de configuración"</string>
<string name="notification_done" msgid="5279426047273930175">"Listo"</string>
<string name="color_and_appearance" msgid="1254323855964993144">"Color y apariencia"</string>
@@ -556,8 +544,7 @@
<item msgid="2139628951880142927">"Mostrar el porcentaje durante la carga (predeterminado)"</item>
<item msgid="3327323682209964956">"No mostrar este ícono"</item>
</string-array>
- <!-- no translation found for other (4060683095962566764) -->
- <skip />
+ <string name="other" msgid="4060683095962566764">"Otros"</string>
<string name="accessibility_divider" msgid="5903423481953635044">"Divisor de pantalla dividida"</string>
<string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Mover hacia abajo"</string>
<string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Mover hacia arriba"</string>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index bd9cc00..b3eda73 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -207,8 +207,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Más tiempo."</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Menos tiempo."</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Linterna desactivada."</string>
- <!-- no translation found for accessibility_quick_settings_flashlight_unavailable (8012811023312280810) -->
- <skip />
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"La linterna no está disponible."</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Linterna activada."</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Linterna desactivada."</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Linterna activada."</string>
@@ -457,34 +456,23 @@
<string name="enable_bluetooth_title" msgid="5027037706500635269">"¿Activar Bluetooth?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Para poder conectar tu teclado a tu tablet, debes activar el Bluetooth."</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Activar"</string>
- <!-- no translation found for show_silently (6841966539811264192) -->
- <skip />
- <!-- no translation found for block (2734508760962682611) -->
- <skip />
- <!-- no translation found for do_not_silence (6878060322594892441) -->
- <skip />
- <!-- no translation found for do_not_silence_block (4070647971382232311) -->
- <skip />
- <!-- no translation found for tuner_full_importance_settings (8103289238676424226) -->
- <skip />
+ <string name="show_silently" msgid="6841966539811264192">"Mostrar notificaciones de forma silenciosa"</string>
+ <string name="block" msgid="2734508760962682611">"Bloquear todas las notificaciones"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"No silenciar"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"No silenciar ni bloquear"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Mostrar ajustes de importancia por completo"</string>
<string name="blocked_importance" msgid="5198578988978234161">"Bloqueado"</string>
- <!-- no translation found for min_importance (1901894910809414782) -->
- <skip />
+ <string name="min_importance" msgid="1901894910809414782">"Importancia mínima"</string>
<string name="low_importance" msgid="4109929986107147930">"Poco importante"</string>
<string name="default_importance" msgid="8192107689995742653">"Importancia normal"</string>
<string name="high_importance" msgid="1527066195614050263">"Muy importante"</string>
<string name="max_importance" msgid="5089005872719563894">"Urgente"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"No mostrar estas notificaciones"</string>
- <!-- no translation found for notification_importance_min (1938190340516905748) -->
- <skip />
- <!-- no translation found for notification_importance_low (3657252049508213048) -->
- <skip />
- <!-- no translation found for notification_importance_default (4466466472622442175) -->
- <skip />
- <!-- no translation found for notification_importance_high (2135428926525093825) -->
- <skip />
- <!-- no translation found for notification_importance_max (5806278962376556491) -->
- <skip />
+ <string name="notification_importance_min" msgid="1938190340516905748">"Mostrar en la parte inferior de la lista de notificaciones de forma silenciosa"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"Mostrar estas notificaciones de forma silenciosa"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"Permitir que estas notificaciones reproduzcan sonidos"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"Mostrar en la pantalla y permitir sonido"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"Mostrar en la parte superior de la lista de notificaciones, mostrar en la pantalla y permitir sonido"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Más ajustes"</string>
<string name="notification_done" msgid="5279426047273930175">"Listo"</string>
<string name="color_and_appearance" msgid="1254323855964993144">"Color y aspecto"</string>
@@ -557,8 +545,7 @@
<item msgid="2139628951880142927">"Mostrar porcentaje durante la carga (predeterminado)"</item>
<item msgid="3327323682209964956">"No mostrar este icono"</item>
</string-array>
- <!-- no translation found for other (4060683095962566764) -->
- <skip />
+ <string name="other" msgid="4060683095962566764">"Otros"</string>
<string name="accessibility_divider" msgid="5903423481953635044">"Dividir la pantalla"</string>
<string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Bajar"</string>
<string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Subir"</string>
diff --git a/packages/SystemUI/res/values-eu-rES/strings.xml b/packages/SystemUI/res/values-eu-rES/strings.xml
index a245bf7..3f8e844 100644
--- a/packages/SystemUI/res/values-eu-rES/strings.xml
+++ b/packages/SystemUI/res/values-eu-rES/strings.xml
@@ -207,8 +207,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Denbora gehiago."</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Denbora gutxiago."</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Flasha desaktibatuta dago."</string>
- <!-- no translation found for accessibility_quick_settings_flashlight_unavailable (8012811023312280810) -->
- <skip />
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Linterna ez dago erabilgarri."</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Flasha aktibatuta dago."</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Flasha desaktibatu egin da."</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Flasha aktibatu egin da."</string>
@@ -309,9 +308,9 @@
<string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Garbitu"</string>
<string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"Aplikazioak ez du onartzen leiho bat baino gehiago erabiltzea"</string>
<string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"Aplikazioak ez du onartzen leiho bat baino gehiago erabiltzea"</string>
- <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Banaketa horizontala"</string>
- <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Banaketa bertikala"</string>
- <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Banaketa pertsonalizatua"</string>
+ <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Zatitze horizontala"</string>
+ <string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Zatitze bertikala"</string>
+ <string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Zatitze pertsonalizatua"</string>
<string name="expanded_header_battery_charged" msgid="5945855970267657951">"Kargatuta"</string>
<string name="expanded_header_battery_charging" msgid="205623198487189724">"Kargatzen"</string>
<string name="expanded_header_battery_charging_with_time" msgid="457559884275395376">"<xliff:g id="CHARGING_TIME">%s</xliff:g> falta zaizkio guztiz kargatzeko"</string>
@@ -456,34 +455,23 @@
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Bluetooth eginbidea aktibatu nahi duzu?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Teklatua tabletara konektatzeko, Bluetooth eginbidea aktibatu behar duzu."</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Aktibatu"</string>
- <!-- no translation found for show_silently (6841966539811264192) -->
- <skip />
- <!-- no translation found for block (2734508760962682611) -->
- <skip />
- <!-- no translation found for do_not_silence (6878060322594892441) -->
- <skip />
- <!-- no translation found for do_not_silence_block (4070647971382232311) -->
- <skip />
- <!-- no translation found for tuner_full_importance_settings (8103289238676424226) -->
- <skip />
+ <string name="show_silently" msgid="6841966539811264192">"Erakutsi jakinarazpenak soinurik egin gabe"</string>
+ <string name="block" msgid="2734508760962682611">"Blokeatu jakinarazpen guztiak"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"Ez isilarazi"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"Ez isilarazi edo blokeatu"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Erakutsi garrantzia handiko jakinarazpenen ezarpenak"</string>
<string name="blocked_importance" msgid="5198578988978234161">"Blokeatuta"</string>
- <!-- no translation found for min_importance (1901894910809414782) -->
- <skip />
+ <string name="min_importance" msgid="1901894910809414782">"Gutxieneko garrantzia"</string>
<string name="low_importance" msgid="4109929986107147930">"Garrantzi txikia"</string>
<string name="default_importance" msgid="8192107689995742653">"Garrantzi normala"</string>
<string name="high_importance" msgid="1527066195614050263">"Garrantzi handia"</string>
<string name="max_importance" msgid="5089005872719563894">"Premiazkoa"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"Ez erakutsi jakinarazpen hauek inoiz"</string>
- <!-- no translation found for notification_importance_min (1938190340516905748) -->
- <skip />
- <!-- no translation found for notification_importance_low (3657252049508213048) -->
- <skip />
- <!-- no translation found for notification_importance_default (4466466472622442175) -->
- <skip />
- <!-- no translation found for notification_importance_high (2135428926525093825) -->
- <skip />
- <!-- no translation found for notification_importance_max (5806278962376556491) -->
- <skip />
+ <string name="notification_importance_min" msgid="1938190340516905748">"Erakutsi jakinarazpen hauek zerrendaren behealdean, baina soinurik egin gabe"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"Erakutsi jakinarazpen hauek, baina soinurik egin gabe"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"Egin soinua jakinarazpen hauek jasotzean"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"Agerrarazi jakinarazpen hauek pantailan eta egin soinua"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"Erakutsi jakinarazpen hauek zerrendaren goialdean, agerrarazi pantailan eta egin soinua"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Ezarpen gehiago"</string>
<string name="notification_done" msgid="5279426047273930175">"Eginda"</string>
<string name="color_and_appearance" msgid="1254323855964993144">"Kolorea eta itxura"</string>
@@ -497,7 +485,7 @@
<string name="use_dark_theme" msgid="2900938704964299312">"Erabili gai iluna Android sistema eragilean"</string>
<string name="adjust_tint" msgid="3398569573231409878">"Doitu kolorea"</string>
<string name="adjust_brightness" msgid="980039329808178246">"Doitu distira"</string>
- <string name="night_mode_disclaimer" msgid="598914896926759578">"Gai iluna Android sistema eragileko eremu nagusietan aplikatzen da. Normalean gai argian bistaratzen dira eremu horiek, adibidez, Ezarpenak atala."</string>
+ <string name="night_mode_disclaimer" msgid="598914896926759578">"Gai iluna Android sistema eragileko eremu nagusietan aplikatzen da. Normalean gai argian bistaratzen dira eremu horiek, adibidez, Ezarpenak atalean."</string>
<string name="color_apply" msgid="9212602012641034283">"Aplikatu"</string>
<string name="color_revert_title" msgid="4746666545480534663">"Berretsi ezarpenak"</string>
<string name="color_revert_message" msgid="9116001069397996691">"Baliteke gailua kolore-ezarpen batzuekin ezin erabili izatea. Kolore-ezarpenak berresteko, sakatu Ados. Bestela, hamar segundoren buruan berrezarriko dira ezarpenak."</string>
@@ -556,8 +544,7 @@
<item msgid="2139628951880142927">"Erakutsi ehunekoa kargatu bitartean (balio lehenetsia)"</item>
<item msgid="3327323682209964956">"Ez erakutsi ikonoa"</item>
</string-array>
- <!-- no translation found for other (4060683095962566764) -->
- <skip />
+ <string name="other" msgid="4060683095962566764">"Beste bat"</string>
<string name="accessibility_divider" msgid="5903423481953635044">"Pantaila-zatitzailea"</string>
<string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Eraman behera"</string>
<string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Eraman gora"</string>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index 2243191..8b3fb5e 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -207,8 +207,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Lisää aikaa."</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Vähennä aikaa."</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Taskulamppu on pois päältä."</string>
- <!-- no translation found for accessibility_quick_settings_flashlight_unavailable (8012811023312280810) -->
- <skip />
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Taskulamppu ei ole käytettävissä."</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Taskulamppu on päällä."</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Taskulamppu poistettiin käytöstä."</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Taskulamppu otettiin käyttöön."</string>
@@ -456,34 +455,23 @@
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Otetaanko Bluetooth käyttöön?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Jotta voit yhdistää näppäimistön tablettiisi, sinun on ensin otettava Bluetooth käyttöön."</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Ota käyttöön"</string>
- <!-- no translation found for show_silently (6841966539811264192) -->
- <skip />
- <!-- no translation found for block (2734508760962682611) -->
- <skip />
- <!-- no translation found for do_not_silence (6878060322594892441) -->
- <skip />
- <!-- no translation found for do_not_silence_block (4070647971382232311) -->
- <skip />
- <!-- no translation found for tuner_full_importance_settings (8103289238676424226) -->
- <skip />
+ <string name="show_silently" msgid="6841966539811264192">"Näytä ilmoitukset hiljennettyinä"</string>
+ <string name="block" msgid="2734508760962682611">"Estä kaikki ilmoitukset"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"Älä hiljennä"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"Älä hiljennä tai estä"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Näytä kaikki tärkeysasetukset"</string>
<string name="blocked_importance" msgid="5198578988978234161">"Estetyt"</string>
- <!-- no translation found for min_importance (1901894910809414782) -->
- <skip />
+ <string name="min_importance" msgid="1901894910809414782">"Pienin tärkeys"</string>
<string name="low_importance" msgid="4109929986107147930">"Ei kovin tärkeä"</string>
<string name="default_importance" msgid="8192107689995742653">"Tärkeä"</string>
<string name="high_importance" msgid="1527066195614050263">"Hyvin tärkeä"</string>
<string name="max_importance" msgid="5089005872719563894">"Kiireellinen"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"Älä koskaan näytä näitä ilmoituksia"</string>
- <!-- no translation found for notification_importance_min (1938190340516905748) -->
- <skip />
- <!-- no translation found for notification_importance_low (3657252049508213048) -->
- <skip />
- <!-- no translation found for notification_importance_default (4466466472622442175) -->
- <skip />
- <!-- no translation found for notification_importance_high (2135428926525093825) -->
- <skip />
- <!-- no translation found for notification_importance_max (5806278962376556491) -->
- <skip />
+ <string name="notification_importance_min" msgid="1938190340516905748">"Hiljennä ilmoitukset ja näytä ne ilmoitusluettelon alaosassa."</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"Näytä nämä ilmoitukset hiljennettyinä."</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"Salli näiden ilmoitusten äänet."</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"Näytä ilmoitukset näytöllä ja salli niiden äänet."</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"Näytä ilmoitukset näytöllä ja ilmoitusluettelon yläosassa ja salli niiden äänet."</string>
<string name="notification_more_settings" msgid="816306283396553571">"Lisäasetukset"</string>
<string name="notification_done" msgid="5279426047273930175">"Valmis"</string>
<string name="color_and_appearance" msgid="1254323855964993144">"Väri ja ulkoasu"</string>
@@ -556,8 +544,7 @@
<item msgid="2139628951880142927">"Näytä prosenttiluku latauksen aikana (oletus)"</item>
<item msgid="3327323682209964956">"Älä näytä tätä kuvaketta"</item>
</string-array>
- <!-- no translation found for other (4060683095962566764) -->
- <skip />
+ <string name="other" msgid="4060683095962566764">"Muu"</string>
<string name="accessibility_divider" msgid="5903423481953635044">"Näytön jakaja"</string>
<string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Siirrä alaspäin"</string>
<string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Siirrä ylöspäin"</string>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index b957dba..e0beeca 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -207,8 +207,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Plus longtemps"</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Moins longtemps."</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Lampe de poche désactivée."</string>
- <!-- no translation found for accessibility_quick_settings_flashlight_unavailable (8012811023312280810) -->
- <skip />
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Lampe de poche indisponible."</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Lampe de poche activée."</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Lampe de poche désactivée."</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Lampe de poche activée."</string>
@@ -456,34 +455,23 @@
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Activer Bluetooth?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Pour connecter votre clavier à votre tablette, vous devez d\'abord activer la connectivité Bluetooth."</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Activer"</string>
- <!-- no translation found for show_silently (6841966539811264192) -->
- <skip />
- <!-- no translation found for block (2734508760962682611) -->
- <skip />
- <!-- no translation found for do_not_silence (6878060322594892441) -->
- <skip />
- <!-- no translation found for do_not_silence_block (4070647971382232311) -->
- <skip />
- <!-- no translation found for tuner_full_importance_settings (8103289238676424226) -->
- <skip />
+ <string name="show_silently" msgid="6841966539811264192">"Afficher les notifications en mode silencieux"</string>
+ <string name="block" msgid="2734508760962682611">"Bloquer toutes les notifications"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"Ne pas activer le mode silencieux"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"Ne pas activer le mode silencieux ni bloquer"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Afficher les paramètres d\'importance complets"</string>
<string name="blocked_importance" msgid="5198578988978234161">"Bloquée"</string>
- <!-- no translation found for min_importance (1901894910809414782) -->
- <skip />
+ <string name="min_importance" msgid="1901894910809414782">"Importance minimale"</string>
<string name="low_importance" msgid="4109929986107147930">"Importance faible"</string>
<string name="default_importance" msgid="8192107689995742653">"Importance normale"</string>
<string name="high_importance" msgid="1527066195614050263">"Importance élevée"</string>
<string name="max_importance" msgid="5089005872719563894">"Importance urgente"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"Ne jamais afficher ces notifications"</string>
- <!-- no translation found for notification_importance_min (1938190340516905748) -->
- <skip />
- <!-- no translation found for notification_importance_low (3657252049508213048) -->
- <skip />
- <!-- no translation found for notification_importance_default (4466466472622442175) -->
- <skip />
- <!-- no translation found for notification_importance_high (2135428926525093825) -->
- <skip />
- <!-- no translation found for notification_importance_max (5806278962376556491) -->
- <skip />
+ <string name="notification_importance_min" msgid="1938190340516905748">"Afficher en mode silencieux au bas de la liste de notifications"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"Afficher ces notifications en mode silencieux"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"Autoriser ces notifications à émettre des sons"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"Afficher sur l\'écran et émettre un son"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"Afficher en haut de la liste des notifications, afficher sur l\'écran et émettre un son"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Plus de paramètres"</string>
<string name="notification_done" msgid="5279426047273930175">"Terminé"</string>
<string name="color_and_appearance" msgid="1254323855964993144">"Couleur et apparence"</string>
@@ -556,8 +544,7 @@
<item msgid="2139628951880142927">"Montrer le pourcentage durant la charge (par défaut)"</item>
<item msgid="3327323682209964956">"Ne pas afficher cette icône"</item>
</string-array>
- <!-- no translation found for other (4060683095962566764) -->
- <skip />
+ <string name="other" msgid="4060683095962566764">"Autre"</string>
<string name="accessibility_divider" msgid="5903423481953635044">"Séparateur d\'écran partagé"</string>
<string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Déplacer vers le bas"</string>
<string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Déplacer vers le haut"</string>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index a7bf20b..9ef6392 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -207,8 +207,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Plus longtemps"</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Moins longtemps"</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Lampe de poche désactivée."</string>
- <!-- no translation found for accessibility_quick_settings_flashlight_unavailable (8012811023312280810) -->
- <skip />
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Lampe de poche indisponible."</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Lampe de poche activée."</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Lampe de poche désactivée."</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Lampe de poche activée."</string>
@@ -456,34 +455,23 @@
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Activer le Bluetooth ?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Pour connecter un clavier à votre tablette, vous devez avoir activé le Bluetooth."</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Activer"</string>
- <!-- no translation found for show_silently (6841966539811264192) -->
- <skip />
- <!-- no translation found for block (2734508760962682611) -->
- <skip />
- <!-- no translation found for do_not_silence (6878060322594892441) -->
- <skip />
- <!-- no translation found for do_not_silence_block (4070647971382232311) -->
- <skip />
- <!-- no translation found for tuner_full_importance_settings (8103289238676424226) -->
- <skip />
+ <string name="show_silently" msgid="6841966539811264192">"Afficher les notifications en mode silencieux"</string>
+ <string name="block" msgid="2734508760962682611">"Bloquer toutes les notifications"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"Ne pas activer le mode silencieux"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"Ne pas activer le mode silencieux ni bloquer"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Afficher les paramètres d\'importance complets"</string>
<string name="blocked_importance" msgid="5198578988978234161">"Bloquées"</string>
- <!-- no translation found for min_importance (1901894910809414782) -->
- <skip />
+ <string name="min_importance" msgid="1901894910809414782">"Importance minimale"</string>
<string name="low_importance" msgid="4109929986107147930">"Importance faible"</string>
<string name="default_importance" msgid="8192107689995742653">"Importance normale"</string>
<string name="high_importance" msgid="1527066195614050263">"Importance élevée"</string>
<string name="max_importance" msgid="5089005872719563894">"Urgent"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"Ne jamais afficher ces notifications"</string>
- <!-- no translation found for notification_importance_min (1938190340516905748) -->
- <skip />
- <!-- no translation found for notification_importance_low (3657252049508213048) -->
- <skip />
- <!-- no translation found for notification_importance_default (4466466472622442175) -->
- <skip />
- <!-- no translation found for notification_importance_high (2135428926525093825) -->
- <skip />
- <!-- no translation found for notification_importance_max (5806278962376556491) -->
- <skip />
+ <string name="notification_importance_min" msgid="1938190340516905748">"Afficher au bas de la liste des notifications en mode silencieux"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"Afficher ces notifications en mode silencieux"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"Autoriser ces notifications à émettre des sons"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"Afficher sur l\'écran et émettre un son"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"Afficher en haut de la liste des notifications, afficher sur l\'écran et émettre un son"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Plus de paramètres"</string>
<string name="notification_done" msgid="5279426047273930175">"Terminé"</string>
<string name="color_and_appearance" msgid="1254323855964993144">"Couleur et apparence"</string>
@@ -556,8 +544,7 @@
<item msgid="2139628951880142927">"Afficher le pourcentage lorsque l\'appareil est en charge (option par défaut)"</item>
<item msgid="3327323682209964956">"Ne plus afficher cette icône"</item>
</string-array>
- <!-- no translation found for other (4060683095962566764) -->
- <skip />
+ <string name="other" msgid="4060683095962566764">"Autre"</string>
<string name="accessibility_divider" msgid="5903423481953635044">"Séparateur d\'écran partagé"</string>
<string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Déplacer vers le bas"</string>
<string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Déplacer vers le haut"</string>
diff --git a/packages/SystemUI/res/values-gl-rES/strings.xml b/packages/SystemUI/res/values-gl-rES/strings.xml
index d24c424..bb85708 100644
--- a/packages/SystemUI/res/values-gl-rES/strings.xml
+++ b/packages/SystemUI/res/values-gl-rES/strings.xml
@@ -207,8 +207,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Máis tempo."</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Menos tempo."</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Lanterna desactivada."</string>
- <!-- no translation found for accessibility_quick_settings_flashlight_unavailable (8012811023312280810) -->
- <skip />
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"A lanterna non está dispoñible."</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Lanterna activada."</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Desactivouse a lanterna."</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Activouse a lanterna."</string>
@@ -456,34 +455,23 @@
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Queres activar o Bluetooth?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Para conectar o teu teclado co tablet, primeiro tes que activar o Bluetooth."</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Activar"</string>
- <!-- no translation found for show_silently (6841966539811264192) -->
- <skip />
- <!-- no translation found for block (2734508760962682611) -->
- <skip />
- <!-- no translation found for do_not_silence (6878060322594892441) -->
- <skip />
- <!-- no translation found for do_not_silence_block (4070647971382232311) -->
- <skip />
- <!-- no translation found for tuner_full_importance_settings (8103289238676424226) -->
- <skip />
+ <string name="show_silently" msgid="6841966539811264192">"Mostrar notificacións de forma silenciosa"</string>
+ <string name="block" msgid="2734508760962682611">"Bloquear todas as notificacións"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"Non silenciar"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"Non silenciar nin bloquear"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Mostrar a configuración completa da importancia"</string>
<string name="blocked_importance" msgid="5198578988978234161">"Bloqueada"</string>
- <!-- no translation found for min_importance (1901894910809414782) -->
- <skip />
+ <string name="min_importance" msgid="1901894910809414782">"Importancia mínima"</string>
<string name="low_importance" msgid="4109929986107147930">"Importancia baixa"</string>
<string name="default_importance" msgid="8192107689995742653">"Importancia normal"</string>
<string name="high_importance" msgid="1527066195614050263">"Importancia alta"</string>
<string name="max_importance" msgid="5089005872719563894">"Importancia urxente"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"Non mostrar nunca estas notificacións"</string>
- <!-- no translation found for notification_importance_min (1938190340516905748) -->
- <skip />
- <!-- no translation found for notification_importance_low (3657252049508213048) -->
- <skip />
- <!-- no translation found for notification_importance_default (4466466472622442175) -->
- <skip />
- <!-- no translation found for notification_importance_high (2135428926525093825) -->
- <skip />
- <!-- no translation found for notification_importance_max (5806278962376556491) -->
- <skip />
+ <string name="notification_importance_min" msgid="1938190340516905748">"Mostrar de forma silenciosa na parte inferior da lista de notificacións"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"Mostrar estas notificacións de forma silenciosa"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"Permitir que esta notificación emita son"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"Mostrar na pantalla e permitir que emita son"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"Mostrar na parte superior da lista de notificacións, amosar na pantalla e permitir que emita son"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Máis opcións"</string>
<string name="notification_done" msgid="5279426047273930175">"Feito"</string>
<string name="color_and_appearance" msgid="1254323855964993144">"Cor e aspecto"</string>
@@ -556,8 +544,7 @@
<item msgid="2139628951880142927">"Mostrar porcentaxe durante a carga (predeterminado)"</item>
<item msgid="3327323682209964956">"Non mostrar esta icona"</item>
</string-array>
- <!-- no translation found for other (4060683095962566764) -->
- <skip />
+ <string name="other" msgid="4060683095962566764">"Outros"</string>
<string name="accessibility_divider" msgid="5903423481953635044">"Divisor de pantalla dividida"</string>
<string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Baixar"</string>
<string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Subir"</string>
diff --git a/packages/SystemUI/res/values-hy-rAM/strings.xml b/packages/SystemUI/res/values-hy-rAM/strings.xml
index 08dfb23..09e7f70b 100644
--- a/packages/SystemUI/res/values-hy-rAM/strings.xml
+++ b/packages/SystemUI/res/values-hy-rAM/strings.xml
@@ -207,8 +207,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Ավելացնել ժամանակը:"</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Պակասեցնել ժամանակը:"</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Լապտերն անջատված է:"</string>
- <!-- no translation found for accessibility_quick_settings_flashlight_unavailable (8012811023312280810) -->
- <skip />
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Լապտերն անհասանելի է:"</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Լապտերը միացված է:"</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Լապտերն անջատվեց:"</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Լապտերը միացավ:"</string>
@@ -456,34 +455,23 @@
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Միացնե՞լ Bluetooth-ը:"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Ստեղնաշարը ձեր պլանշետին միացնելու համար նախ անհրաժեշտ է միացնել Bluetooth-ը:"</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Միացնել"</string>
- <!-- no translation found for show_silently (6841966539811264192) -->
- <skip />
- <!-- no translation found for block (2734508760962682611) -->
- <skip />
- <!-- no translation found for do_not_silence (6878060322594892441) -->
- <skip />
- <!-- no translation found for do_not_silence_block (4070647971382232311) -->
- <skip />
- <!-- no translation found for tuner_full_importance_settings (8103289238676424226) -->
- <skip />
+ <string name="show_silently" msgid="6841966539811264192">"Ցույց տալ ծանուցումներն առանց ձայնային ազդանշանի"</string>
+ <string name="block" msgid="2734508760962682611">"Արգելափակել բոլոր ծանուցումները"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"Ձայնը չանջատել"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"Ձայնը չանջատել և չարգելափակել"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Ցույց տալ կարևորության բոլոր կարգավորումները"</string>
<string name="blocked_importance" msgid="5198578988978234161">"Արգելափակված"</string>
- <!-- no translation found for min_importance (1901894910809414782) -->
- <skip />
+ <string name="min_importance" msgid="1901894910809414782">"Նվազագույն կարևորություն"</string>
<string name="low_importance" msgid="4109929986107147930">"Ցածր կարևորություն"</string>
<string name="default_importance" msgid="8192107689995742653">"Սովորական կարևորություն"</string>
<string name="high_importance" msgid="1527066195614050263">"Բարձր կարևորություն"</string>
<string name="max_importance" msgid="5089005872719563894">"Հրատապ կարևորություն"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"Երբեք չցուցադրել այս ծանուցումները"</string>
- <!-- no translation found for notification_importance_min (1938190340516905748) -->
- <skip />
- <!-- no translation found for notification_importance_low (3657252049508213048) -->
- <skip />
- <!-- no translation found for notification_importance_default (4466466472622442175) -->
- <skip />
- <!-- no translation found for notification_importance_high (2135428926525093825) -->
- <skip />
- <!-- no translation found for notification_importance_max (5806278962376556491) -->
- <skip />
+ <string name="notification_importance_min" msgid="1938190340516905748">"Ցուցադրել ծանուցումների ցանկի ներքևում առանց ձայնային ազդանշանի"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"Ցուցադրել այս ծանուցումներն առանց ձայնային ազդանշանի"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"Թույլ տալ այս ծանուցումներին ձայնային ազդանշան հնչեցնել"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"Թռուցիկ ցուցադրել էկրանին և թույլատրել ձայնային ազդանշանը"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"Ցույց տալ ծանուցումների ցանկի վերևում, թռուցիկ ցուցադրել էկրանին և թույլատրել ձայնային ազդանշանը"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Այլ կարգավորումներ"</string>
<string name="notification_done" msgid="5279426047273930175">"Պատրաստ է"</string>
<string name="color_and_appearance" msgid="1254323855964993144">"Գույնը և արտաքին տեսքը"</string>
@@ -556,8 +544,7 @@
<item msgid="2139628951880142927">"Ցույց տալ տոկոսը լիցքավորելու ժամանակ (կանխադրված է)"</item>
<item msgid="3327323682209964956">"Ցույց չտալ այս պատկերակը"</item>
</string-array>
- <!-- no translation found for other (4060683095962566764) -->
- <skip />
+ <string name="other" msgid="4060683095962566764">"Այլ"</string>
<string name="accessibility_divider" msgid="5903423481953635044">"Տրոհված էկրանի բաժանիչ"</string>
<string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Տեղափոխել ներքև"</string>
<string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Տեղափոխել վերև"</string>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index 3fa41be..46340a7 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -207,8 +207,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Lebih lama."</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Lebih cepat."</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Senter nonaktif."</string>
- <!-- no translation found for accessibility_quick_settings_flashlight_unavailable (8012811023312280810) -->
- <skip />
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Senter tidak tersedia."</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Senter aktif."</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Senter dinonaktifkan."</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Senter diaktifkan."</string>
@@ -456,34 +455,23 @@
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Aktifkan Bluetooth?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Untuk menghubungkan keyboard dengan tablet, terlebih dahulu aktifkan Bluetooth."</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Aktifkan"</string>
- <!-- no translation found for show_silently (6841966539811264192) -->
- <skip />
- <!-- no translation found for block (2734508760962682611) -->
- <skip />
- <!-- no translation found for do_not_silence (6878060322594892441) -->
- <skip />
- <!-- no translation found for do_not_silence_block (4070647971382232311) -->
- <skip />
- <!-- no translation found for tuner_full_importance_settings (8103289238676424226) -->
- <skip />
+ <string name="show_silently" msgid="6841966539811264192">"Tampilkan notifikasi tanpa suara"</string>
+ <string name="block" msgid="2734508760962682611">"Blokir semua notifikasi"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"Jangan bisukan"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"Jangan bisukan atau blokir"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Tampilkan setelan lengkap nilai penting"</string>
<string name="blocked_importance" msgid="5198578988978234161">"Diblokir"</string>
- <!-- no translation found for min_importance (1901894910809414782) -->
- <skip />
+ <string name="min_importance" msgid="1901894910809414782">"Nilai penting min"</string>
<string name="low_importance" msgid="4109929986107147930">"Tingkat kepentingan: rendah"</string>
<string name="default_importance" msgid="8192107689995742653">"Tingkat kepentingan: normal"</string>
<string name="high_importance" msgid="1527066195614050263">"Tingkat kepentingan: tinggi"</string>
<string name="max_importance" msgid="5089005872719563894">"Tingkat kepentingan: darurat"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"Jangan pernah tunjukkan notifikasi ini"</string>
- <!-- no translation found for notification_importance_min (1938190340516905748) -->
- <skip />
- <!-- no translation found for notification_importance_low (3657252049508213048) -->
- <skip />
- <!-- no translation found for notification_importance_default (4466466472622442175) -->
- <skip />
- <!-- no translation found for notification_importance_high (2135428926525093825) -->
- <skip />
- <!-- no translation found for notification_importance_max (5806278962376556491) -->
- <skip />
+ <string name="notification_importance_min" msgid="1938190340516905748">"Tampilkan di bagian bawah daftar notifikasi tanpa suara"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"Tampilkan notifikasi ini tanpa suara"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"Izinkan notifikasi ini bersuara"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"Muncul di layar dan izinkan suara"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"Tampilkan di bagian atas daftar notifikasi, muncul di layar, dan izinkan suara"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Setelan lainnya"</string>
<string name="notification_done" msgid="5279426047273930175">"Selesai"</string>
<string name="color_and_appearance" msgid="1254323855964993144">"Warna dan tampilan"</string>
@@ -556,8 +544,7 @@
<item msgid="2139628951880142927">"Tampilkan persentase saat mengisi daya (default)"</item>
<item msgid="3327323682209964956">"Jangan tampilkan ikon ini"</item>
</string-array>
- <!-- no translation found for other (4060683095962566764) -->
- <skip />
+ <string name="other" msgid="4060683095962566764">"Lainnya"</string>
<string name="accessibility_divider" msgid="5903423481953635044">"Pembagi layar terpisah"</string>
<string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Turunkan"</string>
<string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Naikkan"</string>
diff --git a/packages/SystemUI/res/values-is-rIS/strings.xml b/packages/SystemUI/res/values-is-rIS/strings.xml
index e3c3aa8..89708de 100644
--- a/packages/SystemUI/res/values-is-rIS/strings.xml
+++ b/packages/SystemUI/res/values-is-rIS/strings.xml
@@ -207,8 +207,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Meiri tími."</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Minni tími."</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Slökkt á vasaljósi."</string>
- <!-- no translation found for accessibility_quick_settings_flashlight_unavailable (8012811023312280810) -->
- <skip />
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Vasaljós ekki tiltækt"</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Kveikt á vasaljósi."</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Slökkt á vasaljósi."</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Kveikt á vasaljósi."</string>
@@ -456,34 +455,23 @@
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Kveikja á Bluetooth?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Til að geta tengt lyklaborðið við spjaldtölvuna þarftu fyrst að kveikja á Bluetooth."</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Kveikja"</string>
- <!-- no translation found for show_silently (6841966539811264192) -->
- <skip />
- <!-- no translation found for block (2734508760962682611) -->
- <skip />
- <!-- no translation found for do_not_silence (6878060322594892441) -->
- <skip />
- <!-- no translation found for do_not_silence_block (4070647971382232311) -->
- <skip />
- <!-- no translation found for tuner_full_importance_settings (8103289238676424226) -->
- <skip />
+ <string name="show_silently" msgid="6841966539811264192">"Sýna tilkynningar án hljóðs"</string>
+ <string name="block" msgid="2734508760962682611">"Loka á allar tilkynningar"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"Ekki þagga"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"Hvorki þagga né útiloka"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Sýna stillingar fyrir mikilvægi"</string>
<string name="blocked_importance" msgid="5198578988978234161">"Útilokuð"</string>
- <!-- no translation found for min_importance (1901894910809414782) -->
- <skip />
+ <string name="min_importance" msgid="1901894910809414782">"Lítill forgangur"</string>
<string name="low_importance" msgid="4109929986107147930">"Ekki svo mikilvægt"</string>
<string name="default_importance" msgid="8192107689995742653">"Venjulegt mikilvægi"</string>
<string name="high_importance" msgid="1527066195614050263">"Mjög mikilvægt"</string>
<string name="max_importance" msgid="5089005872719563894">"Afar áríðandi"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"Aldrei sýna þessar tilkynningar"</string>
- <!-- no translation found for notification_importance_min (1938190340516905748) -->
- <skip />
- <!-- no translation found for notification_importance_low (3657252049508213048) -->
- <skip />
- <!-- no translation found for notification_importance_default (4466466472622442175) -->
- <skip />
- <!-- no translation found for notification_importance_high (2135428926525093825) -->
- <skip />
- <!-- no translation found for notification_importance_max (5806278962376556491) -->
- <skip />
+ <string name="notification_importance_min" msgid="1938190340516905748">"Sýna neðst á tilkynningalistanum án hljóðs"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"Sýna þessar tilkynningar án hljóðs"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"Leyfa þessum tilkynningum að spila hljóð"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"Birta á skjánum og leyfa hljóð"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"Sýna efst á tilkynningalistanum, birta á skjánum og leyfa hljóð"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Fleiri stillingar"</string>
<string name="notification_done" msgid="5279426047273930175">"Lokið"</string>
<string name="color_and_appearance" msgid="1254323855964993144">"Litur og útlit"</string>
@@ -556,8 +544,7 @@
<item msgid="2139628951880142927">"Sýna hlutfall meðan á hleðslu stendur (sjálfgefið)"</item>
<item msgid="3327323682209964956">"Ekki sýna þetta tákn"</item>
</string-array>
- <!-- no translation found for other (4060683095962566764) -->
- <skip />
+ <string name="other" msgid="4060683095962566764">"Annað"</string>
<string name="accessibility_divider" msgid="5903423481953635044">"Skjáskipting"</string>
<string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Færa niður"</string>
<string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Færa upp"</string>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index 5266ba8..d6622e3 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -207,8 +207,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Più tempo."</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Meno tempo."</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Torcia spenta."</string>
- <!-- no translation found for accessibility_quick_settings_flashlight_unavailable (8012811023312280810) -->
- <skip />
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Torcia non disponibile."</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Torcia accesa."</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Torcia disattivata."</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Torcia attivata."</string>
@@ -456,34 +455,23 @@
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Attivare il Bluetooth?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Per connettere la tastiera al tablet, devi prima attivare il Bluetooth."</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Attiva"</string>
- <!-- no translation found for show_silently (6841966539811264192) -->
- <skip />
- <!-- no translation found for block (2734508760962682611) -->
- <skip />
- <!-- no translation found for do_not_silence (6878060322594892441) -->
- <skip />
- <!-- no translation found for do_not_silence_block (4070647971382232311) -->
- <skip />
- <!-- no translation found for tuner_full_importance_settings (8103289238676424226) -->
- <skip />
+ <string name="show_silently" msgid="6841966539811264192">"Mostra silenziosamente le notifiche"</string>
+ <string name="block" msgid="2734508760962682611">"Blocca tutte le notifiche"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"Non disattivare i suoni"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"Non disattivare i suoni e non bloccare"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Mostra impostazioni importanza complete"</string>
<string name="blocked_importance" msgid="5198578988978234161">"Bloccata"</string>
- <!-- no translation found for min_importance (1901894910809414782) -->
- <skip />
+ <string name="min_importance" msgid="1901894910809414782">"Importanza min"</string>
<string name="low_importance" msgid="4109929986107147930">"Importanza scarsa"</string>
<string name="default_importance" msgid="8192107689995742653">"Importanza normale"</string>
<string name="high_importance" msgid="1527066195614050263">"Importanza elevata"</string>
<string name="max_importance" msgid="5089005872719563894">"Importanza urgente"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"Non mostrare mai queste notifiche"</string>
- <!-- no translation found for notification_importance_min (1938190340516905748) -->
- <skip />
- <!-- no translation found for notification_importance_low (3657252049508213048) -->
- <skip />
- <!-- no translation found for notification_importance_default (4466466472622442175) -->
- <skip />
- <!-- no translation found for notification_importance_high (2135428926525093825) -->
- <skip />
- <!-- no translation found for notification_importance_max (5806278962376556491) -->
- <skip />
+ <string name="notification_importance_min" msgid="1938190340516905748">"Mostra silenziosamente nella parte inferiore dell\'elenco delle notifiche"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"Mostra silenziosamente queste notifiche"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"Attiva i suoni per queste notifiche"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"Apri sullo schermo e attiva l\'audio"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"Mostra in cima all\'elenco delle notifiche, apri sullo schermo e attiva l\'audio"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Altre impostazioni"</string>
<string name="notification_done" msgid="5279426047273930175">"Fine"</string>
<string name="color_and_appearance" msgid="1254323855964993144">"Colore e aspetto"</string>
@@ -556,8 +544,7 @@
<item msgid="2139628951880142927">"Mostra la percentuale quando in carica (opzione predefinita)"</item>
<item msgid="3327323682209964956">"Non mostrare questa icona"</item>
</string-array>
- <!-- no translation found for other (4060683095962566764) -->
- <skip />
+ <string name="other" msgid="4060683095962566764">"Altro"</string>
<string name="accessibility_divider" msgid="5903423481953635044">"Strumento per schermo diviso"</string>
<string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Sposta giù"</string>
<string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Sposta su"</string>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index a13f975f4..ed44624 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -209,8 +209,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"יותר זמן."</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"פחות זמן."</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"הפנס כבוי."</string>
- <!-- no translation found for accessibility_quick_settings_flashlight_unavailable (8012811023312280810) -->
- <skip />
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"פנס אינו זמין."</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"הפנס מופעל."</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"הפנס נכבה."</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"הפנס הופעל."</string>
@@ -458,34 +457,23 @@
<string name="enable_bluetooth_title" msgid="5027037706500635269">"האם להפעיל את ה-Bluetooth?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"כדי לחבר את המקלדת לטאבלט, תחילה עליך להפעיל את ה-Bluetooth."</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"הפעל"</string>
- <!-- no translation found for show_silently (6841966539811264192) -->
- <skip />
- <!-- no translation found for block (2734508760962682611) -->
- <skip />
- <!-- no translation found for do_not_silence (6878060322594892441) -->
- <skip />
- <!-- no translation found for do_not_silence_block (4070647971382232311) -->
- <skip />
- <!-- no translation found for tuner_full_importance_settings (8103289238676424226) -->
- <skip />
+ <string name="show_silently" msgid="6841966539811264192">"הצג הודעות בלי להשמיע צליל"</string>
+ <string name="block" msgid="2734508760962682611">"חסום את כל ההודעות"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"לא להשתיק"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"לא להשתיק או לחסום"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"הצג את הגדרות החשיבות במלואן"</string>
<string name="blocked_importance" msgid="5198578988978234161">"חסום"</string>
- <!-- no translation found for min_importance (1901894910809414782) -->
- <skip />
+ <string name="min_importance" msgid="1901894910809414782">"חשיבות מינימלית"</string>
<string name="low_importance" msgid="4109929986107147930">"חשיבות נמוכה"</string>
<string name="default_importance" msgid="8192107689995742653">"חשיבות רגילה"</string>
<string name="high_importance" msgid="1527066195614050263">"חשיבות גבוהה"</string>
<string name="max_importance" msgid="5089005872719563894">"חשיבות דחופה"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"לעולם אל תציג את ההודעות האלה"</string>
- <!-- no translation found for notification_importance_min (1938190340516905748) -->
- <skip />
- <!-- no translation found for notification_importance_low (3657252049508213048) -->
- <skip />
- <!-- no translation found for notification_importance_default (4466466472622442175) -->
- <skip />
- <!-- no translation found for notification_importance_high (2135428926525093825) -->
- <skip />
- <!-- no translation found for notification_importance_max (5806278962376556491) -->
- <skip />
+ <string name="notification_importance_min" msgid="1938190340516905748">"הצג בסוף רשימת ההודעות בלי להשמיע צליל"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"הצג את ההודעות האלה בלי להשמיע צליל"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"אשר להודעות אלה להשמיע צליל"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"הצג לרגע על גבי המסך ואשר השמעת צליל"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"הצג בראש רשימת ההודעות, הצג לרגע על גבי המסך ואשר השמעת צליל"</string>
<string name="notification_more_settings" msgid="816306283396553571">"הגדרות נוספות"</string>
<string name="notification_done" msgid="5279426047273930175">"סיום"</string>
<string name="color_and_appearance" msgid="1254323855964993144">"צבע ומראה"</string>
@@ -499,7 +487,7 @@
<string name="use_dark_theme" msgid="2900938704964299312">"השתמש בעיצוב כהה למערכת ההפעלה של Android."</string>
<string name="adjust_tint" msgid="3398569573231409878">"התאמת גוון"</string>
<string name="adjust_brightness" msgid="980039329808178246">"התאמת בהירות"</string>
- <string name="night_mode_disclaimer" msgid="598914896926759578">"העיצוב הכהה מוחל על התחומים העיקריים במערכת ההפעלה של Android שמוצגים בדרך כלל בעיצוב בהיר, כמו \'הגדרות\'."</string>
+ <string name="night_mode_disclaimer" msgid="598914896926759578">"העיצוב הכהה מוחל על התחומים העיקריים במערכת ההפעלה Android שמוצגים בדרך כלל בעיצוב בהיר, כמו \'הגדרות\'."</string>
<string name="color_apply" msgid="9212602012641034283">"החל"</string>
<string name="color_revert_title" msgid="4746666545480534663">"אישור הגדרות"</string>
<string name="color_revert_message" msgid="9116001069397996691">"הגדרות צבע מסוימות עלולות להפוך את המכשיר הזה לבלתי שמיש. לחץ על אישור כדי לאשר את הגדרות הצבע האלה, אחרת הגדרות אלה יתאפסו לאחר 10 שניות."</string>
@@ -558,8 +546,7 @@
<item msgid="2139628951880142927">"הצג באחוזים בזמן טעינה (ברירת מחדל)"</item>
<item msgid="3327323682209964956">"אל תציג את הסמל הזה"</item>
</string-array>
- <!-- no translation found for other (4060683095962566764) -->
- <skip />
+ <string name="other" msgid="4060683095962566764">"אחר"</string>
<string name="accessibility_divider" msgid="5903423481953635044">"מחלק מסך מפוצל"</string>
<string name="accessibility_action_divider_move_down" msgid="704893304141890042">"הזז למטה"</string>
<string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"הזז למעלה"</string>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index d3a8b2c..f104703 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -207,8 +207,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"長くします。"</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"短くします。"</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"ライトがOFFです。"</string>
- <!-- no translation found for accessibility_quick_settings_flashlight_unavailable (8012811023312280810) -->
- <skip />
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"ライトを使用できません。"</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"ライトがONです。"</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"ライトをOFFにしました。"</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"ライトをONにしました。"</string>
@@ -456,34 +455,23 @@
<string name="enable_bluetooth_title" msgid="5027037706500635269">"BluetoothをONにしますか?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"タブレットでキーボードに接続するには、最初にBluetoothをONにする必要があります。"</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"ONにする"</string>
- <!-- no translation found for show_silently (6841966539811264192) -->
- <skip />
- <!-- no translation found for block (2734508760962682611) -->
- <skip />
- <!-- no translation found for do_not_silence (6878060322594892441) -->
- <skip />
- <!-- no translation found for do_not_silence_block (4070647971382232311) -->
- <skip />
- <!-- no translation found for tuner_full_importance_settings (8103289238676424226) -->
- <skip />
+ <string name="show_silently" msgid="6841966539811264192">"通知をマナーモードで表示する"</string>
+ <string name="block" msgid="2734508760962682611">"通知をすべてブロックする"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"音声で知らせる"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"音声で知らせる / ブロックしない"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"重要度の設定をすべて表示"</string>
<string name="blocked_importance" msgid="5198578988978234161">"ブロック中"</string>
- <!-- no translation found for min_importance (1901894910809414782) -->
- <skip />
+ <string name="min_importance" msgid="1901894910809414782">"重要度: 最低"</string>
<string name="low_importance" msgid="4109929986107147930">"重要度: 低"</string>
<string name="default_importance" msgid="8192107689995742653">"重要度: 中"</string>
<string name="high_importance" msgid="1527066195614050263">"重要度: 高"</string>
<string name="max_importance" msgid="5089005872719563894">"重要度: 緊急"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"今後はこの通知を表示しない"</string>
- <!-- no translation found for notification_importance_min (1938190340516905748) -->
- <skip />
- <!-- no translation found for notification_importance_low (3657252049508213048) -->
- <skip />
- <!-- no translation found for notification_importance_default (4466466472622442175) -->
- <skip />
- <!-- no translation found for notification_importance_high (2135428926525093825) -->
- <skip />
- <!-- no translation found for notification_importance_max (5806278962376556491) -->
- <skip />
+ <string name="notification_importance_min" msgid="1938190340516905748">"通知リストの末尾にマナーモードで表示する"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"この通知をマナーモードで表示する"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"通知を音声で知らせる"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"画面に数秒間表示し、音声でも知らせる"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"通知リストの先頭に表示し、画面に数秒間表示し、音声でも知らせる"</string>
<string name="notification_more_settings" msgid="816306283396553571">"詳細設定"</string>
<string name="notification_done" msgid="5279426047273930175">"完了"</string>
<string name="color_and_appearance" msgid="1254323855964993144">"色と表示"</string>
@@ -559,8 +547,7 @@
<item msgid="2139628951880142927">"変更時に割合を表示(デフォルト)"</item>
<item msgid="3327323682209964956">"このアイコンを表示しない"</item>
</string-array>
- <!-- no translation found for other (4060683095962566764) -->
- <skip />
+ <string name="other" msgid="4060683095962566764">"その他"</string>
<string name="accessibility_divider" msgid="5903423481953635044">"分割画面の分割線"</string>
<string name="accessibility_action_divider_move_down" msgid="704893304141890042">"下に移動"</string>
<string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"上に移動"</string>
diff --git a/packages/SystemUI/res/values-ka-rGE/strings.xml b/packages/SystemUI/res/values-ka-rGE/strings.xml
index d14a3c9..b365eb3 100644
--- a/packages/SystemUI/res/values-ka-rGE/strings.xml
+++ b/packages/SystemUI/res/values-ka-rGE/strings.xml
@@ -207,8 +207,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"მეტი დრო."</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"ნაკლები დრო."</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"ფანარი გამორთულია."</string>
- <!-- no translation found for accessibility_quick_settings_flashlight_unavailable (8012811023312280810) -->
- <skip />
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"ფანარი მიუწვდომელია."</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"ფანარი ჩართულია."</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"ფანარი გამოირთო."</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"ფანარი ჩაირთო."</string>
@@ -456,34 +455,23 @@
<string name="enable_bluetooth_title" msgid="5027037706500635269">"გსურთ Bluetooth-ის ჩართვა?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"კლავიატურის ტაბლეტთან დასაკავშირებლად, ჯერ უნდა ჩართოთ Bluetooth."</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"ჩართვა"</string>
- <!-- no translation found for show_silently (6841966539811264192) -->
- <skip />
- <!-- no translation found for block (2734508760962682611) -->
- <skip />
- <!-- no translation found for do_not_silence (6878060322594892441) -->
- <skip />
- <!-- no translation found for do_not_silence_block (4070647971382232311) -->
- <skip />
- <!-- no translation found for tuner_full_importance_settings (8103289238676424226) -->
- <skip />
+ <string name="show_silently" msgid="6841966539811264192">"შეტყობინებების უხმოდ ჩვენება"</string>
+ <string name="block" msgid="2734508760962682611">"ყველა შეტყობინების დაბლოკვა"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"არ გაჩუმდეს"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"არ გაჩუმდეს ან დაიბლოკოს"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"მნიშვნელობის დონის სრული პარამეტრების ჩვენება"</string>
<string name="blocked_importance" msgid="5198578988978234161">"დაბლოკილი"</string>
- <!-- no translation found for min_importance (1901894910809414782) -->
- <skip />
+ <string name="min_importance" msgid="1901894910809414782">"მინიმალური"</string>
<string name="low_importance" msgid="4109929986107147930">"დაბალი პრიორიტეტი"</string>
<string name="default_importance" msgid="8192107689995742653">"ჩვეულებრივი პრიორიტეტი"</string>
<string name="high_importance" msgid="1527066195614050263">"მაღალი პრიორიტეტი"</string>
<string name="max_importance" msgid="5089005872719563894">"გადაუდებელი"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"ამ შეტყობინებების ჩვენების შეწყვეტა"</string>
- <!-- no translation found for notification_importance_min (1938190340516905748) -->
- <skip />
- <!-- no translation found for notification_importance_low (3657252049508213048) -->
- <skip />
- <!-- no translation found for notification_importance_default (4466466472622442175) -->
- <skip />
- <!-- no translation found for notification_importance_high (2135428926525093825) -->
- <skip />
- <!-- no translation found for notification_importance_max (5806278962376556491) -->
- <skip />
+ <string name="notification_importance_min" msgid="1938190340516905748">"შეტყობინებების სიის ბოლოში, უხმოდ ჩვენება"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"ამ შეტყობინებების უხმოდ ჩვენება"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"ამ შეტყობინებებისთვის ხმის გამოცემის დაშვება"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"შეტყობინებების პირდაპირ ეკრანზე ჩვენება და ხმის დაშვება"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"შეტყობინებების სიის თავში ჩვენება, პირდაპირ ეკრანზე გამოჩენა და ხმის დაშვება"</string>
<string name="notification_more_settings" msgid="816306283396553571">"დამატებითი პარამეტრები"</string>
<string name="notification_done" msgid="5279426047273930175">"მზადაა"</string>
<string name="color_and_appearance" msgid="1254323855964993144">"ფერი და იერსახე"</string>
@@ -556,8 +544,7 @@
<item msgid="2139628951880142927">"პროცენტულობის დატენვისას ჩვენება (ნაგულისხმევი)"</item>
<item msgid="3327323682209964956">"აღარ მაჩვენო ეს ხატულა"</item>
</string-array>
- <!-- no translation found for other (4060683095962566764) -->
- <skip />
+ <string name="other" msgid="4060683095962566764">"სხვა"</string>
<string name="accessibility_divider" msgid="5903423481953635044">"გაყოფილი ეკრანის რეჟიმის გამყოფი"</string>
<string name="accessibility_action_divider_move_down" msgid="704893304141890042">"ქვემოთ გადატანა"</string>
<string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"ზემოთ გადატანა"</string>
diff --git a/packages/SystemUI/res/values-kk-rKZ/strings.xml b/packages/SystemUI/res/values-kk-rKZ/strings.xml
index a2346b3..f8c54b6 100644
--- a/packages/SystemUI/res/values-kk-rKZ/strings.xml
+++ b/packages/SystemUI/res/values-kk-rKZ/strings.xml
@@ -207,8 +207,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Көбірек уақыт."</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Азырақ уақыт."</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Қол шам өшірулі."</string>
- <!-- no translation found for accessibility_quick_settings_flashlight_unavailable (8012811023312280810) -->
- <skip />
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Жарқыл қол жетімді емес."</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Қол шам қосулы."</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Қол шам өшірілді."</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Қол шам қосылды."</string>
@@ -457,34 +456,23 @@
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Bluetooth функциясын қосу керек пе?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Пернетақтаны планшетке қосу үшін алдымен Bluetooth функциясын қосу керек."</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Қосу"</string>
- <!-- no translation found for show_silently (6841966539811264192) -->
- <skip />
- <!-- no translation found for block (2734508760962682611) -->
- <skip />
- <!-- no translation found for do_not_silence (6878060322594892441) -->
- <skip />
- <!-- no translation found for do_not_silence_block (4070647971382232311) -->
- <skip />
- <!-- no translation found for tuner_full_importance_settings (8103289238676424226) -->
- <skip />
+ <string name="show_silently" msgid="6841966539811264192">"Хабарландыруларды үнсіз көрсету"</string>
+ <string name="block" msgid="2734508760962682611">"Барлық хабарландыруларды бұғаттау"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"Үнін өшірмеу"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"Үнін өшірмеу немесе бұғаттамау"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Толық маңыздылық параметрлерін көрсету"</string>
<string name="blocked_importance" msgid="5198578988978234161">"Бөгелген"</string>
- <!-- no translation found for min_importance (1901894910809414782) -->
- <skip />
+ <string name="min_importance" msgid="1901894910809414782">"Ең аз маңыздылық"</string>
<string name="low_importance" msgid="4109929986107147930">"Төмен маңыздылық"</string>
<string name="default_importance" msgid="8192107689995742653">"Қалыпты маңыздылық"</string>
<string name="high_importance" msgid="1527066195614050263">"Жоғары маңыздылық"</string>
<string name="max_importance" msgid="5089005872719563894">"Шұғыл маңыздылық"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"Осы хабарландыруларды ешқашан көрсетпеу"</string>
- <!-- no translation found for notification_importance_min (1938190340516905748) -->
- <skip />
- <!-- no translation found for notification_importance_low (3657252049508213048) -->
- <skip />
- <!-- no translation found for notification_importance_default (4466466472622442175) -->
- <skip />
- <!-- no translation found for notification_importance_high (2135428926525093825) -->
- <skip />
- <!-- no translation found for notification_importance_max (5806278962376556491) -->
- <skip />
+ <string name="notification_importance_min" msgid="1938190340516905748">"Хабарландырулар тізімнің төменгі жағында үнсіз көрсету"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"Осы хабарландыруларды үнсіз көрсету"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"Осы хабарландыруға дыбыстар шығаруға рұқсат ету"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"Экранда көрсету және дыбыс шығаруға рұқсат ету"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"Хабарландырулар тізімінің жоғарғы жағында көрсету, экранда көрсету және дыбысқа рұқсат ету"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Қосымша параметрлер"</string>
<string name="notification_done" msgid="5279426047273930175">"Дайын"</string>
<string name="color_and_appearance" msgid="1254323855964993144">"Түс және сыртқы түрі"</string>
@@ -498,7 +486,7 @@
<string name="use_dark_theme" msgid="2900938704964299312">"Android ОЖ үшін күңгірт тақырыпты пайдалану"</string>
<string name="adjust_tint" msgid="3398569573231409878">"Реңкті реттеу"</string>
<string name="adjust_brightness" msgid="980039329808178246">"Жарықтықты реттеу"</string>
- <string name="night_mode_disclaimer" msgid="598914896926759578">"Күңгірт тақырып Android операциялық жүйесінің әдетте ашық тақырыпта көрсетілетін негізгі аумақтарына қолданылады, мысалы, \"Параметрлер\" тармағына."</string>
+ <string name="night_mode_disclaimer" msgid="598914896926759578">"Күңгірт тақырып Android операциялық жүйесінің әдетте \"Параметрлер\" сияқты ашық тақырыпта көрсетілетін негізгі аумақтарына қолданылады."</string>
<string name="color_apply" msgid="9212602012641034283">"Қолдану"</string>
<string name="color_revert_title" msgid="4746666545480534663">"Параметрлерді растау"</string>
<string name="color_revert_message" msgid="9116001069397996691">"Кейбір түс параметрлері бұл құрылғыны пайдалану мүмкін емес етуі мүмкін. Бұл түс параметрлерін растау үшін OK түймесін басыңыз, әйтпесе параметрлер 10 секундтан кейін ысырылады."</string>
@@ -557,8 +545,7 @@
<item msgid="2139628951880142927">"Зарядтау кезінде пайызды көрсету (әдепкі)"</item>
<item msgid="3327323682209964956">"Бұл белгішені көрсетпеу"</item>
</string-array>
- <!-- no translation found for other (4060683095962566764) -->
- <skip />
+ <string name="other" msgid="4060683095962566764">"Басқа"</string>
<string name="accessibility_divider" msgid="5903423481953635044">"Бөлінген экран бөлгіші"</string>
<string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Төмен қарай жылжыту"</string>
<string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Жоғары қарай жылжыту"</string>
diff --git a/packages/SystemUI/res/values-ky-rKG/strings.xml b/packages/SystemUI/res/values-ky-rKG/strings.xml
index d5ac252..66a34f0 100644
--- a/packages/SystemUI/res/values-ky-rKG/strings.xml
+++ b/packages/SystemUI/res/values-ky-rKG/strings.xml
@@ -73,7 +73,7 @@
<string name="screenshot_saved_title" msgid="6461865960961414961">"Скриншот тартылды."</string>
<string name="screenshot_saved_text" msgid="1152839647677558815">"Тийип, скриншотту көрүңүз."</string>
<string name="screenshot_failed_title" msgid="705781116746922771">"Скриншот кылынбай жатат."</string>
- <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Эстутумда бош орун чектелүү болгондуктан скриншот сакталбай жатат."</string>
+ <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Сактагычта бош орун аз болгондуктан скриншот сакталбай жатат."</string>
<string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Скриншот тартууга колдонмо же ишканаңыз уруксат бербейт."</string>
<string name="usb_preference_title" msgid="6551050377388882787">"USB менен файл өткөрүү мүмкүнчүлүктөрү"</string>
<string name="use_mtp_button_title" msgid="4333504413563023626">"Медиа ойноткуч катары кошуу (MTP)"</string>
@@ -207,8 +207,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Көбүрөөк убакыт."</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Азыраак убакыт."</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Колчырак өчүк."</string>
- <!-- no translation found for accessibility_quick_settings_flashlight_unavailable (8012811023312280810) -->
- <skip />
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Кол чырак жок."</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Колчырак күйүк."</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Колчырак өчүрүлдү."</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Колчырак күйгүзүлдү."</string>
@@ -307,8 +306,8 @@
<string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> коопсуз режиминде өчүрүлдү."</string>
<string name="recents_history_button_label" msgid="5153358867807604821">"Таржымал"</string>
<string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"Тазалоо"</string>
- <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"Бул колдонмо мульти-терезени колдоого албайт"</string>
- <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"Колдонмо мульти-терезени колдоого албайт"</string>
+ <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"Бул колдонмодо бир нече терезе режими колдоого алынбайт"</string>
+ <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"Колдонмодо бир нече терезе режими колдоого алынбайт"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Туурасынан бөлүү"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"Тигинен бөлүү"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"Ыңгайлаштырылган бөлүү"</string>
@@ -456,34 +455,23 @@
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Bluetooth күйгүзүлсүнбү?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Баскычтобуңузду планшетиңизге туташтыруу үчүн, адегенде Bluetooth\'ту күйгүзүшүңүз керек."</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Күйгүзүү"</string>
- <!-- no translation found for show_silently (6841966539811264192) -->
- <skip />
- <!-- no translation found for block (2734508760962682611) -->
- <skip />
- <!-- no translation found for do_not_silence (6878060322594892441) -->
- <skip />
- <!-- no translation found for do_not_silence_block (4070647971382232311) -->
- <skip />
- <!-- no translation found for tuner_full_importance_settings (8103289238676424226) -->
- <skip />
+ <string name="show_silently" msgid="6841966539811264192">"Эскертмелер үнсүз көрсөтүлсүн"</string>
+ <string name="block" msgid="2734508760962682611">"Бардык эскертмелерди бөгөттөө"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"Үнсүз кылынбасын"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"Үнсүз кылынып же бөгөттөлбөсүн"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Маанилүүлүк жөндөөлөрү толук көрсөтүлсүн"</string>
<string name="blocked_importance" msgid="5198578988978234161">"Бөгөттөлгөн"</string>
- <!-- no translation found for min_importance (1901894910809414782) -->
- <skip />
+ <string name="min_importance" msgid="1901894910809414782">"Маанилүүлүгү эң төмөн"</string>
<string name="low_importance" msgid="4109929986107147930">"Маанилүүлүгү төмөн"</string>
<string name="default_importance" msgid="8192107689995742653">"Маанилүүлүгү орточо"</string>
<string name="high_importance" msgid="1527066195614050263">"Маанилүүлүгү жогору"</string>
<string name="max_importance" msgid="5089005872719563894">"Маанилүүлүгү шашылыш"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"Бул эскертмелер эч качан көрсөтүлбөсүн"</string>
- <!-- no translation found for notification_importance_min (1938190340516905748) -->
- <skip />
- <!-- no translation found for notification_importance_low (3657252049508213048) -->
- <skip />
- <!-- no translation found for notification_importance_default (4466466472622442175) -->
- <skip />
- <!-- no translation found for notification_importance_high (2135428926525093825) -->
- <skip />
- <!-- no translation found for notification_importance_max (5806278962376556491) -->
- <skip />
+ <string name="notification_importance_min" msgid="1938190340516905748">"Эскертмелер тизмесинин соңунда үнсүз көрсөтүлсүн"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"Бул эскертмелер үнсүз көрсөтүлсүн"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"Бул эскертмелер добуш чыгарышына уруксат берилсин"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"Үн менен коштолуп, экранга чыгарылсын"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"Эскертмелер тизмесинин эң башында көрсөтүлүп, үн менен коштолуп, экранга чыгарылсын"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Дагы жөндөөлөр"</string>
<string name="notification_done" msgid="5279426047273930175">"Аткарылды"</string>
<string name="color_and_appearance" msgid="1254323855964993144">"Түсү жана көрүнүшү"</string>
@@ -497,7 +485,7 @@
<string name="use_dark_theme" msgid="2900938704964299312">"Android OS үчүн караңгы тема колдонуу"</string>
<string name="adjust_tint" msgid="3398569573231409878">"Кошумча түсүн тууралоо"</string>
<string name="adjust_brightness" msgid="980039329808178246">"Жарыктыгын тууралоо"</string>
- <string name="night_mode_disclaimer" msgid="598914896926759578">"Адатта жарык темада көрсөтүлгөн Android OS\'тин, Жөндөөлөр сыяктуу негизги аймактарына караңгы тема колдонулат."</string>
+ <string name="night_mode_disclaimer" msgid="598914896926759578">"Адатта жарык темада көрсөтүлүүчү Android тутумунун негизги элементтерине (Жөндөөлөр сыяктуу) колдонула турган караңгы тема."</string>
<string name="color_apply" msgid="9212602012641034283">"Колдонуу"</string>
<string name="color_revert_title" msgid="4746666545480534663">"Жөндөөлөрдү ырастоо"</string>
<string name="color_revert_message" msgid="9116001069397996691">"Айрым түс жөндөөлөрү бул түзмөктү колдонулгус кылып коюшу мүмкүн. Бул түс жөндөөлөрүн ырастоо үчүн OK баскычын чыкылдатыңыз, болбосо бул жөндөөлөр 10 секунддан кийин баштапкы абалына келтирилет."</string>
@@ -556,8 +544,7 @@
<item msgid="2139628951880142927">"Кубаттоо учурунда пайызы көрсөтүлсүн (демейки)"</item>
<item msgid="3327323682209964956">"Бул сөлөкөт көрсөтүлбөсүн"</item>
</string-array>
- <!-- no translation found for other (4060683095962566764) -->
- <skip />
+ <string name="other" msgid="4060683095962566764">"Башка"</string>
<string name="accessibility_divider" msgid="5903423481953635044">"Экранды бөлгүч"</string>
<string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Төмөн жылдыруу"</string>
<string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Жогору жылдыруу"</string>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index a33c76f..bb49c39 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -209,8 +209,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Daugiau laiko."</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Mažiau laiko."</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Blykstė išjungta."</string>
- <!-- no translation found for accessibility_quick_settings_flashlight_unavailable (8012811023312280810) -->
- <skip />
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Blykstė nepasiekiama."</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Blykstė įjungta."</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Blykstė išjungta."</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Blykstė įjungta."</string>
@@ -458,34 +457,23 @@
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Įjungti „Bluetooth“?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Kad galėtumėte prijungti klaviatūrą prie planšetinio kompiuterio, pirmiausia turite įjungti „Bluetooth“."</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Įjungti"</string>
- <!-- no translation found for show_silently (6841966539811264192) -->
- <skip />
- <!-- no translation found for block (2734508760962682611) -->
- <skip />
- <!-- no translation found for do_not_silence (6878060322594892441) -->
- <skip />
- <!-- no translation found for do_not_silence_block (4070647971382232311) -->
- <skip />
- <!-- no translation found for tuner_full_importance_settings (8103289238676424226) -->
- <skip />
+ <string name="show_silently" msgid="6841966539811264192">"Tyliai rodyti pranešimus"</string>
+ <string name="block" msgid="2734508760962682611">"Blokuoti visus pranešimus"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"Netylėti"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"Netylėti arba blokuoti"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Rodyti visos svarbos nustatymus"</string>
<string name="blocked_importance" msgid="5198578988978234161">"Užblokuota"</string>
- <!-- no translation found for min_importance (1901894910809414782) -->
- <skip />
+ <string name="min_importance" msgid="1901894910809414782">"Min. svarba"</string>
<string name="low_importance" msgid="4109929986107147930">"Maža svarba"</string>
<string name="default_importance" msgid="8192107689995742653">"Įprasta svarba"</string>
<string name="high_importance" msgid="1527066195614050263">"Didelė svarba"</string>
<string name="max_importance" msgid="5089005872719563894">"Skubi svarba"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"Niekada nerodyti šių pranešimų"</string>
- <!-- no translation found for notification_importance_min (1938190340516905748) -->
- <skip />
- <!-- no translation found for notification_importance_low (3657252049508213048) -->
- <skip />
- <!-- no translation found for notification_importance_default (4466466472622442175) -->
- <skip />
- <!-- no translation found for notification_importance_high (2135428926525093825) -->
- <skip />
- <!-- no translation found for notification_importance_max (5806278962376556491) -->
- <skip />
+ <string name="notification_importance_min" msgid="1938190340516905748">"Tyliai rodyti pranešimų sąrašo apačioje"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"Tyliai rodyti šiuos pranešimus"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"Leisti šiems pranešimams skambėti"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"Rodyti ekrane ir leisti skambėti"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"Rodyti pranešimų sąrašo viršuje, rodyti ekrane ir leisti skambėti"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Daugiau nustatymų"</string>
<string name="notification_done" msgid="5279426047273930175">"Atlikta"</string>
<string name="color_and_appearance" msgid="1254323855964993144">"Spalva ir išvaizda"</string>
@@ -558,8 +546,7 @@
<item msgid="2139628951880142927">"Rodyti procentus kraunant (numatytasis nustatymas)"</item>
<item msgid="3327323682209964956">"Nerodyti šios piktogramos"</item>
</string-array>
- <!-- no translation found for other (4060683095962566764) -->
- <skip />
+ <string name="other" msgid="4060683095962566764">"Kita"</string>
<string name="accessibility_divider" msgid="5903423481953635044">"Skaidyto ekrano daliklis"</string>
<string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Perkelti žemyn"</string>
<string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Perkelti aukštyn"</string>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index 683e00a..574889e 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -208,8 +208,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Vairāk laika."</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Mazāk laika."</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Apgaismojums ir izslēgts."</string>
- <!-- no translation found for accessibility_quick_settings_flashlight_unavailable (8012811023312280810) -->
- <skip />
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Zibspuldze nav pieejama."</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Apgaismojums ir ieslēgts."</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Apgaismojums ir izslēgts."</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Apgaismojums ir ieslēgts."</string>
@@ -457,34 +456,23 @@
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Vai ieslēgt Bluetooth savienojumu?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Lai pievienotu tastatūru planšetdatoram, vispirms ir jāieslēdz Bluetooth savienojums."</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Ieslēgt"</string>
- <!-- no translation found for show_silently (6841966539811264192) -->
- <skip />
- <!-- no translation found for block (2734508760962682611) -->
- <skip />
- <!-- no translation found for do_not_silence (6878060322594892441) -->
- <skip />
- <!-- no translation found for do_not_silence_block (4070647971382232311) -->
- <skip />
- <!-- no translation found for tuner_full_importance_settings (8103289238676424226) -->
- <skip />
+ <string name="show_silently" msgid="6841966539811264192">"Rādīt paziņojumus bez skaņas signāla"</string>
+ <string name="block" msgid="2734508760962682611">"Bloķēt visus paziņojumus"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"Neizslēgt skaņu"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"Neizslēgt skaņu vai nebloķēt"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Rādīt ļoti svarīgu paziņojumu iestatījumus"</string>
<string name="blocked_importance" msgid="5198578988978234161">"Bloķēts"</string>
- <!-- no translation found for min_importance (1901894910809414782) -->
- <skip />
+ <string name="min_importance" msgid="1901894910809414782">"Minimāls svarīguma līmenis"</string>
<string name="low_importance" msgid="4109929986107147930">"Nav svarīgs"</string>
<string name="default_importance" msgid="8192107689995742653">"Parasts"</string>
<string name="high_importance" msgid="1527066195614050263">"Ļoti svarīgs"</string>
<string name="max_importance" msgid="5089005872719563894">"Steidzams"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"Nekad nerādīt šos paziņojumus"</string>
- <!-- no translation found for notification_importance_min (1938190340516905748) -->
- <skip />
- <!-- no translation found for notification_importance_low (3657252049508213048) -->
- <skip />
- <!-- no translation found for notification_importance_default (4466466472622442175) -->
- <skip />
- <!-- no translation found for notification_importance_high (2135428926525093825) -->
- <skip />
- <!-- no translation found for notification_importance_max (5806278962376556491) -->
- <skip />
+ <string name="notification_importance_min" msgid="1938190340516905748">"Rādīt paziņojumu saraksta apakšdaļā bez skaņas signāla"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"Rādīt šos paziņojumus bez skaņas signāla"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"Atļaut skaņas signālu šiem paziņojumiem"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"Rādīt ekrānā un atļaut skaņas signālu"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"Rādīt paziņojumu saraksta augšdaļā, rādīt ekrānā ar skaņas signālu"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Citi iestatījumi"</string>
<string name="notification_done" msgid="5279426047273930175">"Gatavs"</string>
<string name="color_and_appearance" msgid="1254323855964993144">"Krāsas un izskats"</string>
@@ -557,8 +545,7 @@
<item msgid="2139628951880142927">"Rādīt procentuālo vērtību uzlādes laikā (noklusējums)"</item>
<item msgid="3327323682209964956">"Nerādīt šo ikonu"</item>
</string-array>
- <!-- no translation found for other (4060683095962566764) -->
- <skip />
+ <string name="other" msgid="4060683095962566764">"Citi"</string>
<string name="accessibility_divider" msgid="5903423481953635044">"Ekrāna sadalītājs"</string>
<string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Pārvietot uz leju"</string>
<string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Pārvietot uz augšu"</string>
diff --git a/packages/SystemUI/res/values-mn-rMN/strings.xml b/packages/SystemUI/res/values-mn-rMN/strings.xml
index fea38a9..a69be1f 100644
--- a/packages/SystemUI/res/values-mn-rMN/strings.xml
+++ b/packages/SystemUI/res/values-mn-rMN/strings.xml
@@ -205,8 +205,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Хугацаа нэмэх."</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Хугацаа хасах."</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Флаш гэрэл унтарсан."</string>
- <!-- no translation found for accessibility_quick_settings_flashlight_unavailable (8012811023312280810) -->
- <skip />
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Гэрэлтүүлэгч боломжгүй байна."</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Флаш гэрэл ассан."</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Флаш гэрлийг унтраасан."</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Флаш гэрлийг асаасан."</string>
@@ -454,34 +453,23 @@
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Bluetooth-г асаах уу?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Компьютерийн гараа таблетад холбохын тулд эхлээд Bluetooth-г асаана уу."</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Асаах"</string>
- <!-- no translation found for show_silently (6841966539811264192) -->
- <skip />
- <!-- no translation found for block (2734508760962682611) -->
- <skip />
- <!-- no translation found for do_not_silence (6878060322594892441) -->
- <skip />
- <!-- no translation found for do_not_silence_block (4070647971382232311) -->
- <skip />
- <!-- no translation found for tuner_full_importance_settings (8103289238676424226) -->
- <skip />
+ <string name="show_silently" msgid="6841966539811264192">"Мэдэгдлийг чимээгүй харуулах"</string>
+ <string name="block" msgid="2734508760962682611">"Бүх мэдэгдлийг блоклох"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"Дуугүй болгох хэрэггүй"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"Дууг нь хаах эсвэл блоклох хэрэггүй"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Бүрэн ач холбогдлын тохиргоог харуулах"</string>
<string name="blocked_importance" msgid="5198578988978234161">"Блоклосон"</string>
- <!-- no translation found for min_importance (1901894910809414782) -->
- <skip />
+ <string name="min_importance" msgid="1901894910809414782">"Хамгийн бага ач холбогдол"</string>
<string name="low_importance" msgid="4109929986107147930">"Бага ач холбогдолтой"</string>
<string name="default_importance" msgid="8192107689995742653">"Энгийн ач холбогдолтой"</string>
<string name="high_importance" msgid="1527066195614050263">"Өндөр ач холбогдолтой"</string>
<string name="max_importance" msgid="5089005872719563894">"Яаралтай ач холбогдолтой"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"Эдгээр мэдэгдлийг хэзээ ч харуулахгүй"</string>
- <!-- no translation found for notification_importance_min (1938190340516905748) -->
- <skip />
- <!-- no translation found for notification_importance_low (3657252049508213048) -->
- <skip />
- <!-- no translation found for notification_importance_default (4466466472622442175) -->
- <skip />
- <!-- no translation found for notification_importance_high (2135428926525093825) -->
- <skip />
- <!-- no translation found for notification_importance_max (5806278962376556491) -->
- <skip />
+ <string name="notification_importance_min" msgid="1938190340516905748">"Мэдэгдлийг жагсаалтын доод хэсэгт дуугүй харуулах"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"Эдгээр мэдэгдлийг дуугүй харуулах"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"Эдгээр мэдэгдлийг дуу гаргахыг зөвшөөрөх"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"Дэлгэцэд яаралтайгаар дуутай гаргах"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"Мэдэгдлийг жагсаалтын эхэнд яаралтай дуутай харуулах"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Бусад тохиргоо"</string>
<string name="notification_done" msgid="5279426047273930175">"Дууссан"</string>
<string name="color_and_appearance" msgid="1254323855964993144">"Өнгө, харагдах байдал"</string>
@@ -554,8 +542,7 @@
<item msgid="2139628951880142927">"Цэнэглэх үед хувийг тогтмол харуулах (өгөгдмөл)"</item>
<item msgid="3327323682209964956">"Энэ дүрс тэмдгийг бүү үзүүл"</item>
</string-array>
- <!-- no translation found for other (4060683095962566764) -->
- <skip />
+ <string name="other" msgid="4060683095962566764">"Бусад"</string>
<string name="accessibility_divider" msgid="5903423481953635044">"\"Дэлгэц хуваах\" хуваагч"</string>
<string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Доош зөөх"</string>
<string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Дээш зөөх"</string>
diff --git a/packages/SystemUI/res/values-mr-rIN/strings.xml b/packages/SystemUI/res/values-mr-rIN/strings.xml
index acd9d4e..d99678c 100644
--- a/packages/SystemUI/res/values-mr-rIN/strings.xml
+++ b/packages/SystemUI/res/values-mr-rIN/strings.xml
@@ -207,8 +207,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"अधिक वेळ."</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"कमी वेळ."</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"फ्लॅशलाइट बंद."</string>
- <!-- no translation found for accessibility_quick_settings_flashlight_unavailable (8012811023312280810) -->
- <skip />
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"फ्लॅशलाइट अनुपलब्ध आहे."</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"फ्लॅशलाइट चालू."</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"फ्लॅशलाइट बंद केला."</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"फ्लॅशलाइट चालू केला."</string>
@@ -456,34 +455,23 @@
<string name="enable_bluetooth_title" msgid="5027037706500635269">"ब्लूटुथ सुरू करायचे?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"आपला कीबोर्ड आपल्या टॅब्लेटसह कनेक्ट करण्यासाठी, आपल्याला प्रथम ब्लूटुथ चालू करणे आवश्यक आहे."</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"चालू करा"</string>
- <!-- no translation found for show_silently (6841966539811264192) -->
- <skip />
- <!-- no translation found for block (2734508760962682611) -->
- <skip />
- <!-- no translation found for do_not_silence (6878060322594892441) -->
- <skip />
- <!-- no translation found for do_not_silence_block (4070647971382232311) -->
- <skip />
- <!-- no translation found for tuner_full_importance_settings (8103289238676424226) -->
- <skip />
+ <string name="show_silently" msgid="6841966539811264192">"सूचना शांतपणे दर्शवा"</string>
+ <string name="block" msgid="2734508760962682611">"सर्व सूचना अवरोधित करा"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"शांत करू नका"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"शांत किंवा अवरोधित करू नका"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"पूर्ण महत्त्व सेटिंग्ज दर्शवा"</string>
<string name="blocked_importance" msgid="5198578988978234161">"अवरोधित केले"</string>
- <!-- no translation found for min_importance (1901894910809414782) -->
- <skip />
+ <string name="min_importance" msgid="1901894910809414782">"किमान महत्त्व"</string>
<string name="low_importance" msgid="4109929986107147930">"कमी महत्त्व"</string>
<string name="default_importance" msgid="8192107689995742653">"सामान्य महत्त्व"</string>
<string name="high_importance" msgid="1527066195614050263">"सर्वाधिक महत्व"</string>
<string name="max_importance" msgid="5089005872719563894">"त्वरित महत्त्व"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"या सूचना कधीही दर्शवू नका"</string>
- <!-- no translation found for notification_importance_min (1938190340516905748) -->
- <skip />
- <!-- no translation found for notification_importance_low (3657252049508213048) -->
- <skip />
- <!-- no translation found for notification_importance_default (4466466472622442175) -->
- <skip />
- <!-- no translation found for notification_importance_high (2135428926525093825) -->
- <skip />
- <!-- no translation found for notification_importance_max (5806278962376556491) -->
- <skip />
+ <string name="notification_importance_min" msgid="1938190340516905748">"सूचना सूचीच्या तळाशी शांतपणे दर्शवा"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"या सूचना शांतपणे दर्शवा"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"या सूचनांना ध्वनी चालू करण्याची अनुमती द्या"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"स्क्रीनवर पहा आणि ध्वनीस अनुमती द्या ध्वनीस अनुमती द्या"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"सूचनांच्या शीर्षस्थानी दर्शवा, स्क्रीनवर पहा आणि ध्वनीस अनुमती द्या"</string>
<string name="notification_more_settings" msgid="816306283396553571">"अधिक सेटिंग्ज"</string>
<string name="notification_done" msgid="5279426047273930175">"पूर्ण झाले"</string>
<string name="color_and_appearance" msgid="1254323855964993144">"रंग आणि स्वरूप"</string>
@@ -556,8 +544,7 @@
<item msgid="2139628951880142927">"चार्ज करताना टक्केवारी दर्शवा (डीफॉल्ट)"</item>
<item msgid="3327323682209964956">"हे चिन्ह दर्शवू नका"</item>
</string-array>
- <!-- no translation found for other (4060683095962566764) -->
- <skip />
+ <string name="other" msgid="4060683095962566764">"अन्य"</string>
<string name="accessibility_divider" msgid="5903423481953635044">"विभाजित-स्क्रीन विभाजक"</string>
<string name="accessibility_action_divider_move_down" msgid="704893304141890042">"खाली हलवा"</string>
<string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"वर हलवा"</string>
diff --git a/packages/SystemUI/res/values-ms-rMY/strings.xml b/packages/SystemUI/res/values-ms-rMY/strings.xml
index d204830..a716eef 100644
--- a/packages/SystemUI/res/values-ms-rMY/strings.xml
+++ b/packages/SystemUI/res/values-ms-rMY/strings.xml
@@ -207,8 +207,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Lagi masa."</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Kurang masa."</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Lampu suluh dimatikan."</string>
- <!-- no translation found for accessibility_quick_settings_flashlight_unavailable (8012811023312280810) -->
- <skip />
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Lampu suluh tidak tersedia."</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Lampu suluh dihidupkan."</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Lampu suluh dimatikan."</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Lampu suluh dihidupkan."</string>
@@ -456,34 +455,23 @@
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Hidupkan Bluetooth?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Untuk menyambungkan papan kekunci anda dengan tablet, anda perlu menghidupkan Bluetooth terlebih dahulu."</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Hidupkan"</string>
- <!-- no translation found for show_silently (6841966539811264192) -->
- <skip />
- <!-- no translation found for block (2734508760962682611) -->
- <skip />
- <!-- no translation found for do_not_silence (6878060322594892441) -->
- <skip />
- <!-- no translation found for do_not_silence_block (4070647971382232311) -->
- <skip />
- <!-- no translation found for tuner_full_importance_settings (8103289238676424226) -->
- <skip />
+ <string name="show_silently" msgid="6841966539811264192">"Tunjukkan pemberitahuan secara senyap"</string>
+ <string name="block" msgid="2734508760962682611">"Sekat semua pemberitahuan"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"Jangan senyapkan"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"Jangan senyapkan atau sekat"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Tunjukkan tetapan kepentingan penuh"</string>
<string name="blocked_importance" msgid="5198578988978234161">"Disekat"</string>
- <!-- no translation found for min_importance (1901894910809414782) -->
- <skip />
+ <string name="min_importance" msgid="1901894910809414782">"Kurang penting"</string>
<string name="low_importance" msgid="4109929986107147930">"Kepentingan rendah"</string>
<string name="default_importance" msgid="8192107689995742653">"Kepentingan biasa"</string>
<string name="high_importance" msgid="1527066195614050263">"Kepentingan tinggi"</string>
<string name="max_importance" msgid="5089005872719563894">"Kepentingan segera"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"Jangan sekali-kali tunjukkan pemberitahuan ini"</string>
- <!-- no translation found for notification_importance_min (1938190340516905748) -->
- <skip />
- <!-- no translation found for notification_importance_low (3657252049508213048) -->
- <skip />
- <!-- no translation found for notification_importance_default (4466466472622442175) -->
- <skip />
- <!-- no translation found for notification_importance_high (2135428926525093825) -->
- <skip />
- <!-- no translation found for notification_importance_max (5806278962376556491) -->
- <skip />
+ <string name="notification_importance_min" msgid="1938190340516905748">"Tunjukkan pada bahagian bawah senarai pemberitahuan secara senyap"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"Tunjukkan pemberitahuan ini secara senyap"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"Benarkan pemberitahuan ini berbunyi"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"Intai pada skrin dan benarkan bunyi"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"Tunjukkan pada bahagian atas senarai pemberitahuan, intai pada skrin dan benarkan bunyi"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Lagi tetapan"</string>
<string name="notification_done" msgid="5279426047273930175">"Selesai"</string>
<string name="color_and_appearance" msgid="1254323855964993144">"Warna dan penampilan"</string>
@@ -556,9 +544,8 @@
<item msgid="2139628951880142927">"Tunjukkan peratusan semasa mengecas (lalai)"</item>
<item msgid="3327323682209964956">"Jangan tunjukkan ikon ini"</item>
</string-array>
- <!-- no translation found for other (4060683095962566764) -->
- <skip />
- <string name="accessibility_divider" msgid="5903423481953635044">"Pembahagi skrin terpisah"</string>
+ <string name="other" msgid="4060683095962566764">"Lain-lain"</string>
+ <string name="accessibility_divider" msgid="5903423481953635044">"Pembahagi skrin pisah"</string>
<string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Alih ke bawah"</string>
<string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Alih ke atas"</string>
<string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"Alih ke kiri"</string>
diff --git a/packages/SystemUI/res/values-my-rMM/strings.xml b/packages/SystemUI/res/values-my-rMM/strings.xml
index c88eda2..503b91f 100644
--- a/packages/SystemUI/res/values-my-rMM/strings.xml
+++ b/packages/SystemUI/res/values-my-rMM/strings.xml
@@ -306,8 +306,8 @@
<string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> ကို ဘေးကင်းလုံခြုံသည့်မုဒ်တွင် ပိတ်ထားပါသည်။"</string>
<string name="recents_history_button_label" msgid="5153358867807604821">"မှတ်တမ်း"</string>
<string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"ရှင်းလင်းပါ"</string>
- <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"ဤအက်ပ်သည် ဝင်းဒိုးများစွာတွင်ဖွင့်ရန် မပံ့ပိုးထားပါ"</string>
- <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"အက်ပ်သည် ဝင်းဒိုးများစွာတွင်ဖွင့်ရန် မပံ့ပိုးထားပါ"</string>
+ <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"ဤအက်ပ်သည် ဝင်းဒိုးများစွာဖွင့်ခြင်းကို ပံ့ပိုးမထားပါ"</string>
+ <string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"အက်ပ်သည် ဝင်းဒိုးများစွာဖွင့်ခြင်းကို ပံ့ပိုးမထားပါ"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"ရေပြင်ညီ ပိုင်းမည်"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"ဒေါင်လိုက်ပိုင်းမည်"</string>
<string name="recents_multistack_add_stack_dialog_split_custom" msgid="4177837597513701943">"စိတ်ကြိုက် ပိုင်းမည်"</string>
@@ -545,7 +545,7 @@
<item msgid="3327323682209964956">"ဤသင်္ကေတပုံကို မပြပါနှင့်"</item>
</string-array>
<string name="other" msgid="4060683095962566764">"အခြား"</string>
- <string name="accessibility_divider" msgid="5903423481953635044">"မျက်နှာပြင်ခွဲခြမ်းခြင်း ပိုင်းခြားပေးသည့်စနစ်"</string>
+ <string name="accessibility_divider" msgid="5903423481953635044">"မျက်နှာပြင်ခွဲခြမ်း ပိုင်းခြားပေးသည့်စနစ်"</string>
<string name="accessibility_action_divider_move_down" msgid="704893304141890042">"အောက်သို့ရွှေ့ပါ"</string>
<string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"အပေါ်သို့ရွှေ့ပါ"</string>
<string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"ဘယ်ဘက်သို့ရွှေ့ပါ"</string>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index ac8cc8d..b3de239 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -207,8 +207,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Mer tid."</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Mindre tid."</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Lommelykten er av."</string>
- <!-- no translation found for accessibility_quick_settings_flashlight_unavailable (8012811023312280810) -->
- <skip />
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Lommelykt er ikke tilgjengelig."</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Lommelykten er på."</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Lommelykten er slått av."</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Lommelykten er slått på."</string>
@@ -456,34 +455,23 @@
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Vil du slå på Bluetooth?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"For å koble tastaturet til nettbrettet ditt må du først slå på Bluetooth."</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Slå på"</string>
- <!-- no translation found for show_silently (6841966539811264192) -->
- <skip />
- <!-- no translation found for block (2734508760962682611) -->
- <skip />
- <!-- no translation found for do_not_silence (6878060322594892441) -->
- <skip />
- <!-- no translation found for do_not_silence_block (4070647971382232311) -->
- <skip />
- <!-- no translation found for tuner_full_importance_settings (8103289238676424226) -->
- <skip />
+ <string name="show_silently" msgid="6841966539811264192">"Vis varsler uten lyd"</string>
+ <string name="block" msgid="2734508760962682611">"Blokkér alle varsler"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"Ikke slå av lyden"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"Ikke slå av lyden eller blokkér anrop"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Vis alle viktighetsinnstillingene"</string>
<string name="blocked_importance" msgid="5198578988978234161">"Blokkert"</string>
- <!-- no translation found for min_importance (1901894910809414782) -->
- <skip />
+ <string name="min_importance" msgid="1901894910809414782">"Laveste prioritet"</string>
<string name="low_importance" msgid="4109929986107147930">"Lav viktighet"</string>
<string name="default_importance" msgid="8192107689995742653">"Vanlig viktighet"</string>
<string name="high_importance" msgid="1527066195614050263">"Høy viktighet"</string>
<string name="max_importance" msgid="5089005872719563894">"Svært høy viktighet"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"Aldri vis disse varslene"</string>
- <!-- no translation found for notification_importance_min (1938190340516905748) -->
- <skip />
- <!-- no translation found for notification_importance_low (3657252049508213048) -->
- <skip />
- <!-- no translation found for notification_importance_default (4466466472622442175) -->
- <skip />
- <!-- no translation found for notification_importance_high (2135428926525093825) -->
- <skip />
- <!-- no translation found for notification_importance_max (5806278962376556491) -->
- <skip />
+ <string name="notification_importance_min" msgid="1938190340516905748">"Vis nederst på varsellisten uten lyd"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"Vis disse varslene uten lyd"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"Tillat at disse varslene vises med lyd"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"Vis fort på skjermen og tillat lyd"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"Vis øverst på varsellisten, vis fort på skjermen og tillat lyd"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Flere innstillinger"</string>
<string name="notification_done" msgid="5279426047273930175">"Ferdig"</string>
<string name="color_and_appearance" msgid="1254323855964993144">"Farge og utseende"</string>
@@ -556,8 +544,7 @@
<item msgid="2139628951880142927">"Vis prosentandel under lading (standard)"</item>
<item msgid="3327323682209964956">"Ikke vis dette ikonet"</item>
</string-array>
- <!-- no translation found for other (4060683095962566764) -->
- <skip />
+ <string name="other" msgid="4060683095962566764">"Annet"</string>
<string name="accessibility_divider" msgid="5903423481953635044">"Skilleelement for delt skjerm"</string>
<string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Flytt ned"</string>
<string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Flytt opp"</string>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index c9821ee..974685c 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -209,8 +209,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Więcej czasu."</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Mniej czasu."</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Latarka wyłączona."</string>
- <!-- no translation found for accessibility_quick_settings_flashlight_unavailable (8012811023312280810) -->
- <skip />
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Latarka niedostępna."</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Latarka włączona."</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Latarka została wyłączona."</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Latarka została włączona."</string>
@@ -458,34 +457,23 @@
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Włączyć Bluetooth?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Aby połączyć klawiaturę z tabletem, musisz najpierw włączyć Bluetooth."</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Włącz"</string>
- <!-- no translation found for show_silently (6841966539811264192) -->
- <skip />
- <!-- no translation found for block (2734508760962682611) -->
- <skip />
- <!-- no translation found for do_not_silence (6878060322594892441) -->
- <skip />
- <!-- no translation found for do_not_silence_block (4070647971382232311) -->
- <skip />
- <!-- no translation found for tuner_full_importance_settings (8103289238676424226) -->
- <skip />
+ <string name="show_silently" msgid="6841966539811264192">"Pokazuj powiadomienia bez sygnału dźwiękowego"</string>
+ <string name="block" msgid="2734508760962682611">"Blokuj wszystkie powiadomienia"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"Nie ignoruj"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"Nie ignoruj ani nie blokuj"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Pokaż pełne ustawienia ważności"</string>
<string name="blocked_importance" msgid="5198578988978234161">"Zablokowane"</string>
- <!-- no translation found for min_importance (1901894910809414782) -->
- <skip />
+ <string name="min_importance" msgid="1901894910809414782">"Najmniejsza ważność"</string>
<string name="low_importance" msgid="4109929986107147930">"Mało ważne"</string>
<string name="default_importance" msgid="8192107689995742653">"Ważne"</string>
<string name="high_importance" msgid="1527066195614050263">"Bardzo ważne"</string>
<string name="max_importance" msgid="5089005872719563894">"Pilne"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"Nigdy nie pokazuj tych powiadomień"</string>
- <!-- no translation found for notification_importance_min (1938190340516905748) -->
- <skip />
- <!-- no translation found for notification_importance_low (3657252049508213048) -->
- <skip />
- <!-- no translation found for notification_importance_default (4466466472622442175) -->
- <skip />
- <!-- no translation found for notification_importance_high (2135428926525093825) -->
- <skip />
- <!-- no translation found for notification_importance_max (5806278962376556491) -->
- <skip />
+ <string name="notification_importance_min" msgid="1938190340516905748">"Pokazuj na końcu listy powiadomień bez sygnału dźwiękowego"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"Pokazuj te powiadomienia bez sygnału dźwiękowego"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"Zezwól na sygnalizowanie tych powiadomień dźwiękiem"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"Wyświetlaj na ekranie i sygnalizuj dźwiękiem"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"Pokazuj na początku listy powiadomień, wyświetlaj na ekranie i sygnalizuj dźwiękiem"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Więcej ustawień"</string>
<string name="notification_done" msgid="5279426047273930175">"Gotowe"</string>
<string name="color_and_appearance" msgid="1254323855964993144">"Kolor i wygląd"</string>
@@ -558,8 +546,7 @@
<item msgid="2139628951880142927">"Pokazuj procent podczas ładowania (domyślnie)"</item>
<item msgid="3327323682209964956">"Nie pokazuj tej ikony"</item>
</string-array>
- <!-- no translation found for other (4060683095962566764) -->
- <skip />
+ <string name="other" msgid="4060683095962566764">"Inne"</string>
<string name="accessibility_divider" msgid="5903423481953635044">"Linia dzielenia ekranu"</string>
<string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Przesuń w dół"</string>
<string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Przesuń w górę"</string>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml
index a15a789..3797adc 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -207,8 +207,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Mais tempo."</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Menos tempo."</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Lanterna desativada."</string>
- <!-- no translation found for accessibility_quick_settings_flashlight_unavailable (8012811023312280810) -->
- <skip />
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Lanterna indisponível."</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Lanterna ativada."</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"A lanterna foi desativada."</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"A lanterna foi ativada."</string>
@@ -457,34 +456,23 @@
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Ativar o Bluetooth?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Para conectar o teclado ao tablet, é preciso primeiro ativar o Bluetooth."</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Ativar"</string>
- <!-- no translation found for show_silently (6841966539811264192) -->
- <skip />
- <!-- no translation found for block (2734508760962682611) -->
- <skip />
- <!-- no translation found for do_not_silence (6878060322594892441) -->
- <skip />
- <!-- no translation found for do_not_silence_block (4070647971382232311) -->
- <skip />
- <!-- no translation found for tuner_full_importance_settings (8103289238676424226) -->
- <skip />
+ <string name="show_silently" msgid="6841966539811264192">"Mostrar notificações de forma silenciosa"</string>
+ <string name="block" msgid="2734508760962682611">"Bloquear todas as notificações"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"Não silenciar"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"Não silenciar ou bloquear"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Mostrar todas as configurações de importância"</string>
<string name="blocked_importance" msgid="5198578988978234161">"Bloqueadas"</string>
- <!-- no translation found for min_importance (1901894910809414782) -->
- <skip />
+ <string name="min_importance" msgid="1901894910809414782">"Importância mínima"</string>
<string name="low_importance" msgid="4109929986107147930">"Importância baixa"</string>
<string name="default_importance" msgid="8192107689995742653">"Importância normal"</string>
<string name="high_importance" msgid="1527066195614050263">"Importância elevada"</string>
<string name="max_importance" msgid="5089005872719563894">"Importância urgente"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"Nunca mostrar essas notificações"</string>
- <!-- no translation found for notification_importance_min (1938190340516905748) -->
- <skip />
- <!-- no translation found for notification_importance_low (3657252049508213048) -->
- <skip />
- <!-- no translation found for notification_importance_default (4466466472622442175) -->
- <skip />
- <!-- no translation found for notification_importance_high (2135428926525093825) -->
- <skip />
- <!-- no translation found for notification_importance_max (5806278962376556491) -->
- <skip />
+ <string name="notification_importance_min" msgid="1938190340516905748">"Mostrar na parte inferior da lista de notificações de forma silenciosa"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"Mostrar essas notificações de forma silenciosa"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"Permitir que essas notificações emitam sons"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"Mostrar parcialmente na tela e permitir som"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"Mostrar na parte superior da lista de notificações, mostrar parcialmente na tela e permitir sons"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Mais configurações"</string>
<string name="notification_done" msgid="5279426047273930175">"Concluído"</string>
<string name="color_and_appearance" msgid="1254323855964993144">"Cor e aparência"</string>
@@ -498,7 +486,7 @@
<string name="use_dark_theme" msgid="2900938704964299312">"Usar o tema escuro para o SO Android"</string>
<string name="adjust_tint" msgid="3398569573231409878">"Ajustar tonalidade"</string>
<string name="adjust_brightness" msgid="980039329808178246">"Ajustar brilho"</string>
- <string name="night_mode_disclaimer" msgid="598914896926759578">"O tema escuro é aplicado a áreas centrais do sistema operacional Android que normalmente são exibidas em um tema claro, como asconfigurações."</string>
+ <string name="night_mode_disclaimer" msgid="598914896926759578">"O tema escuro é aplicado a áreas centrais do sistema operacional Android que normalmente são exibidas em um tema claro, como as configurações."</string>
<string name="color_apply" msgid="9212602012641034283">"Aplicar"</string>
<string name="color_revert_title" msgid="4746666545480534663">"Confirmar configurações"</string>
<string name="color_revert_message" msgid="9116001069397996691">"Algumas configurações de cor podem tornar o dispositivo inutilizável. Clique em \"OK\" para confirmar essas configurações de cor; caso contrário, essas configurações serão redefinidas após 10 segundos."</string>
@@ -557,8 +545,7 @@
<item msgid="2139628951880142927">"Mostrar porcentagem durante o carregamento (padrão)"</item>
<item msgid="3327323682209964956">"Não mostrar este ícone"</item>
</string-array>
- <!-- no translation found for other (4060683095962566764) -->
- <skip />
+ <string name="other" msgid="4060683095962566764">"Outros"</string>
<string name="accessibility_divider" msgid="5903423481953635044">"Divisor de tela"</string>
<string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Mover para baixo"</string>
<string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Mover para cima"</string>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index 85d4c79..7ee2554 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -207,8 +207,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Mais tempo."</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Menos tempo."</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Lanterna desligada."</string>
- <!-- no translation found for accessibility_quick_settings_flashlight_unavailable (8012811023312280810) -->
- <skip />
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Lanterna indisponível."</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Lanterna ligada."</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Lanterna desligada."</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Lanterna ligada."</string>
@@ -456,34 +455,23 @@
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Pretende ativar o Bluetooth?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Para ligar o teclado ao tablet, tem de ativar primeiro o Bluetooth."</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Ativar"</string>
- <!-- no translation found for show_silently (6841966539811264192) -->
- <skip />
- <!-- no translation found for block (2734508760962682611) -->
- <skip />
- <!-- no translation found for do_not_silence (6878060322594892441) -->
- <skip />
- <!-- no translation found for do_not_silence_block (4070647971382232311) -->
- <skip />
- <!-- no translation found for tuner_full_importance_settings (8103289238676424226) -->
- <skip />
+ <string name="show_silently" msgid="6841966539811264192">"Mostrar notificações sem som"</string>
+ <string name="block" msgid="2734508760962682611">"Bloquear todas as notificações"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"Não silenciar"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"Não silenciar nem bloquear"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Mostrar definições de importância completas"</string>
<string name="blocked_importance" msgid="5198578988978234161">"Bloqueado"</string>
- <!-- no translation found for min_importance (1901894910809414782) -->
- <skip />
+ <string name="min_importance" msgid="1901894910809414782">"Importância mín."</string>
<string name="low_importance" msgid="4109929986107147930">"Importância baixa"</string>
<string name="default_importance" msgid="8192107689995742653">"Importância normal"</string>
<string name="high_importance" msgid="1527066195614050263">"Importância alta"</string>
<string name="max_importance" msgid="5089005872719563894">"Urgente"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"Nunca mostrar estas notificações"</string>
- <!-- no translation found for notification_importance_min (1938190340516905748) -->
- <skip />
- <!-- no translation found for notification_importance_low (3657252049508213048) -->
- <skip />
- <!-- no translation found for notification_importance_default (4466466472622442175) -->
- <skip />
- <!-- no translation found for notification_importance_high (2135428926525093825) -->
- <skip />
- <!-- no translation found for notification_importance_max (5806278962376556491) -->
- <skip />
+ <string name="notification_importance_min" msgid="1938190340516905748">"Mostrar na parte inferior da lista de notificações sem som"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"Mostrar estas notificações sem som"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"Permitir que estas notificações emitam sons"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"Mostrar no ecrã e permitir som"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"Mostrar na parte superior da lista de notificações, mostrar no ecrã e permitir som"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Mais definições"</string>
<string name="notification_done" msgid="5279426047273930175">"Concluído"</string>
<string name="color_and_appearance" msgid="1254323855964993144">"Cor e aspeto"</string>
@@ -556,8 +544,7 @@
<item msgid="2139628951880142927">"Mostrar a percentagem durante o carregamento (predefinição)"</item>
<item msgid="3327323682209964956">"Não mostrar este ícone"</item>
</string-array>
- <!-- no translation found for other (4060683095962566764) -->
- <skip />
+ <string name="other" msgid="4060683095962566764">"Outro"</string>
<string name="accessibility_divider" msgid="5903423481953635044">"Divisor do ecrã dividido"</string>
<string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Mover para baixo"</string>
<string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Mover para cima"</string>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index a15a789..3797adc 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -207,8 +207,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Mais tempo."</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Menos tempo."</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Lanterna desativada."</string>
- <!-- no translation found for accessibility_quick_settings_flashlight_unavailable (8012811023312280810) -->
- <skip />
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Lanterna indisponível."</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Lanterna ativada."</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"A lanterna foi desativada."</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"A lanterna foi ativada."</string>
@@ -457,34 +456,23 @@
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Ativar o Bluetooth?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Para conectar o teclado ao tablet, é preciso primeiro ativar o Bluetooth."</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Ativar"</string>
- <!-- no translation found for show_silently (6841966539811264192) -->
- <skip />
- <!-- no translation found for block (2734508760962682611) -->
- <skip />
- <!-- no translation found for do_not_silence (6878060322594892441) -->
- <skip />
- <!-- no translation found for do_not_silence_block (4070647971382232311) -->
- <skip />
- <!-- no translation found for tuner_full_importance_settings (8103289238676424226) -->
- <skip />
+ <string name="show_silently" msgid="6841966539811264192">"Mostrar notificações de forma silenciosa"</string>
+ <string name="block" msgid="2734508760962682611">"Bloquear todas as notificações"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"Não silenciar"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"Não silenciar ou bloquear"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Mostrar todas as configurações de importância"</string>
<string name="blocked_importance" msgid="5198578988978234161">"Bloqueadas"</string>
- <!-- no translation found for min_importance (1901894910809414782) -->
- <skip />
+ <string name="min_importance" msgid="1901894910809414782">"Importância mínima"</string>
<string name="low_importance" msgid="4109929986107147930">"Importância baixa"</string>
<string name="default_importance" msgid="8192107689995742653">"Importância normal"</string>
<string name="high_importance" msgid="1527066195614050263">"Importância elevada"</string>
<string name="max_importance" msgid="5089005872719563894">"Importância urgente"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"Nunca mostrar essas notificações"</string>
- <!-- no translation found for notification_importance_min (1938190340516905748) -->
- <skip />
- <!-- no translation found for notification_importance_low (3657252049508213048) -->
- <skip />
- <!-- no translation found for notification_importance_default (4466466472622442175) -->
- <skip />
- <!-- no translation found for notification_importance_high (2135428926525093825) -->
- <skip />
- <!-- no translation found for notification_importance_max (5806278962376556491) -->
- <skip />
+ <string name="notification_importance_min" msgid="1938190340516905748">"Mostrar na parte inferior da lista de notificações de forma silenciosa"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"Mostrar essas notificações de forma silenciosa"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"Permitir que essas notificações emitam sons"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"Mostrar parcialmente na tela e permitir som"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"Mostrar na parte superior da lista de notificações, mostrar parcialmente na tela e permitir sons"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Mais configurações"</string>
<string name="notification_done" msgid="5279426047273930175">"Concluído"</string>
<string name="color_and_appearance" msgid="1254323855964993144">"Cor e aparência"</string>
@@ -498,7 +486,7 @@
<string name="use_dark_theme" msgid="2900938704964299312">"Usar o tema escuro para o SO Android"</string>
<string name="adjust_tint" msgid="3398569573231409878">"Ajustar tonalidade"</string>
<string name="adjust_brightness" msgid="980039329808178246">"Ajustar brilho"</string>
- <string name="night_mode_disclaimer" msgid="598914896926759578">"O tema escuro é aplicado a áreas centrais do sistema operacional Android que normalmente são exibidas em um tema claro, como asconfigurações."</string>
+ <string name="night_mode_disclaimer" msgid="598914896926759578">"O tema escuro é aplicado a áreas centrais do sistema operacional Android que normalmente são exibidas em um tema claro, como as configurações."</string>
<string name="color_apply" msgid="9212602012641034283">"Aplicar"</string>
<string name="color_revert_title" msgid="4746666545480534663">"Confirmar configurações"</string>
<string name="color_revert_message" msgid="9116001069397996691">"Algumas configurações de cor podem tornar o dispositivo inutilizável. Clique em \"OK\" para confirmar essas configurações de cor; caso contrário, essas configurações serão redefinidas após 10 segundos."</string>
@@ -557,8 +545,7 @@
<item msgid="2139628951880142927">"Mostrar porcentagem durante o carregamento (padrão)"</item>
<item msgid="3327323682209964956">"Não mostrar este ícone"</item>
</string-array>
- <!-- no translation found for other (4060683095962566764) -->
- <skip />
+ <string name="other" msgid="4060683095962566764">"Outros"</string>
<string name="accessibility_divider" msgid="5903423481953635044">"Divisor de tela"</string>
<string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Mover para baixo"</string>
<string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Mover para cima"</string>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index fc1ed2f..c2bec08 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -208,8 +208,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Mai mult timp."</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Mai puțin timp."</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Lanterna este dezactivată."</string>
- <!-- no translation found for accessibility_quick_settings_flashlight_unavailable (8012811023312280810) -->
- <skip />
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Lanterna nu este disponibilă."</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Lanterna este activată."</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Lanterna este dezactivată."</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Lanterna este activată."</string>
@@ -457,34 +456,23 @@
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Activați Bluetooth?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Pentru a conecta tastatura la tabletă, mai întâi trebuie să activați Bluetooth."</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Activați"</string>
- <!-- no translation found for show_silently (6841966539811264192) -->
- <skip />
- <!-- no translation found for block (2734508760962682611) -->
- <skip />
- <!-- no translation found for do_not_silence (6878060322594892441) -->
- <skip />
- <!-- no translation found for do_not_silence_block (4070647971382232311) -->
- <skip />
- <!-- no translation found for tuner_full_importance_settings (8103289238676424226) -->
- <skip />
+ <string name="show_silently" msgid="6841966539811264192">"Notificările se afișează fără a se emite un sunet"</string>
+ <string name="block" msgid="2734508760962682611">"Blocați toate notificările"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"Nu dezactivați sunetul"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"Nu dezactivați sunetul și nu blocați"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Afișați toate setările privind importanța"</string>
<string name="blocked_importance" msgid="5198578988978234161">"Blocate"</string>
- <!-- no translation found for min_importance (1901894910809414782) -->
- <skip />
+ <string name="min_importance" msgid="1901894910809414782">"Importanță minimă"</string>
<string name="low_importance" msgid="4109929986107147930">"Importanță redusă"</string>
<string name="default_importance" msgid="8192107689995742653">"Importanță normală"</string>
<string name="high_importance" msgid="1527066195614050263">"Importanță ridicată"</string>
<string name="max_importance" msgid="5089005872719563894">"Importanță: urgente"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"Aceste notificări nu se afișează niciodată"</string>
- <!-- no translation found for notification_importance_min (1938190340516905748) -->
- <skip />
- <!-- no translation found for notification_importance_low (3657252049508213048) -->
- <skip />
- <!-- no translation found for notification_importance_default (4466466472622442175) -->
- <skip />
- <!-- no translation found for notification_importance_high (2135428926525093825) -->
- <skip />
- <!-- no translation found for notification_importance_max (5806278962376556491) -->
- <skip />
+ <string name="notification_importance_min" msgid="1938190340516905748">"Se afișează în partea de jos a listei cu notificări fără a se emite un sunet"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"Aceste notificări se afișează fără a se emite un sunet"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"Permiteți acestor notificări să emită sunete"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"Se afișează pentru o scurtă durată pe ecran și se permite un sunet"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"Apar în partea de sus a listei cu notificări, se afișează pentru scurt timp pe ecran și se permite un sunet"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Mai multe setări"</string>
<string name="notification_done" msgid="5279426047273930175">"Terminat"</string>
<string name="color_and_appearance" msgid="1254323855964993144">"Culoare și aspect"</string>
@@ -557,8 +545,7 @@
<item msgid="2139628951880142927">"Afișează procentajul când se încarcă (prestabilit)"</item>
<item msgid="3327323682209964956">"Nu afișa această pictogramă"</item>
</string-array>
- <!-- no translation found for other (4060683095962566764) -->
- <skip />
+ <string name="other" msgid="4060683095962566764">"Altele"</string>
<string name="accessibility_divider" msgid="5903423481953635044">"Separator pentru ecranul împărțit"</string>
<string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Mutați în jos"</string>
<string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Mutați în sus"</string>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index 5340d95..8ece7fa 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -209,8 +209,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Увеличить время."</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Уменьшить время."</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Фонарик отключен."</string>
- <!-- no translation found for accessibility_quick_settings_flashlight_unavailable (8012811023312280810) -->
- <skip />
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Фонарик недоступен."</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Фонарик включен."</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Фонарик отключен."</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Фонарик включен."</string>
@@ -458,34 +457,23 @@
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Подключение по Bluetooth"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Чтобы подключить клавиатуру к планшету, включите Bluetooth."</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Включить"</string>
- <!-- no translation found for show_silently (6841966539811264192) -->
- <skip />
- <!-- no translation found for block (2734508760962682611) -->
- <skip />
- <!-- no translation found for do_not_silence (6878060322594892441) -->
- <skip />
- <!-- no translation found for do_not_silence_block (4070647971382232311) -->
- <skip />
- <!-- no translation found for tuner_full_importance_settings (8103289238676424226) -->
- <skip />
+ <string name="show_silently" msgid="6841966539811264192">"Показывать без звука"</string>
+ <string name="block" msgid="2734508760962682611">"Блокировать все уведомления"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"Показывать со звуком"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"Не блокировать, показывать со звуком"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Показывать все настройки важности"</string>
<string name="blocked_importance" msgid="5198578988978234161">"Блокировка"</string>
- <!-- no translation found for min_importance (1901894910809414782) -->
- <skip />
+ <string name="min_importance" msgid="1901894910809414782">"Наименьшая важность"</string>
<string name="low_importance" msgid="4109929986107147930">"Низкая важность"</string>
<string name="default_importance" msgid="8192107689995742653">"Средняя важность"</string>
<string name="high_importance" msgid="1527066195614050263">"Высокая важность"</string>
<string name="max_importance" msgid="5089005872719563894">"Крайняя важность"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"Не показывать эти уведомления."</string>
- <!-- no translation found for notification_importance_min (1938190340516905748) -->
- <skip />
- <!-- no translation found for notification_importance_low (3657252049508213048) -->
- <skip />
- <!-- no translation found for notification_importance_default (4466466472622442175) -->
- <skip />
- <!-- no translation found for notification_importance_high (2135428926525093825) -->
- <skip />
- <!-- no translation found for notification_importance_max (5806278962376556491) -->
- <skip />
+ <string name="notification_importance_min" msgid="1938190340516905748">"Показывать без звука в конце списка уведомлений"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"Показывать без звука"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"Показывать со звуком"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"Показывать со звуком поверх всех окон"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"Показывать со звуком в начале списка уведомлений и поверх всех окон"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Другие настройки"</string>
<string name="notification_done" msgid="5279426047273930175">"Готово"</string>
<string name="color_and_appearance" msgid="1254323855964993144">"Цвета и стиль"</string>
@@ -558,8 +546,7 @@
<item msgid="2139628951880142927">"Показывать процент во время зарядки (по умолчанию)"</item>
<item msgid="3327323682209964956">"Не показывать этот значок"</item>
</string-array>
- <!-- no translation found for other (4060683095962566764) -->
- <skip />
+ <string name="other" msgid="4060683095962566764">"Другое"</string>
<string name="accessibility_divider" msgid="5903423481953635044">"Разделитель экрана"</string>
<string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Опустить"</string>
<string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Поднять"</string>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index 446590f..40daf19 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -75,7 +75,7 @@
<string name="screenshot_saved_title" msgid="6461865960961414961">"Snímka obrazovky bola zaznamenaná."</string>
<string name="screenshot_saved_text" msgid="1152839647677558815">"Snímku obrazovky zobrazíte dotykom."</string>
<string name="screenshot_failed_title" msgid="705781116746922771">"Snímku obrazovky sa nepodarilo zachytiť."</string>
- <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Snímku obrazovky nie je možné vytvoriť z dôvodu nedostatku miesta na úložisku."</string>
+ <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Snímku obrazovky nie je možné vytvoriť z dôvodu nedostatku miesta v úložisku."</string>
<string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"Vytváranie snímok obrazovky je zakázané aplikáciou alebo vašou organizáciou."</string>
<string name="usb_preference_title" msgid="6551050377388882787">"Možnosti prenosu súborov USB"</string>
<string name="use_mtp_button_title" msgid="4333504413563023626">"Pripojiť ako prehrávač médií (MTP)"</string>
@@ -209,8 +209,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Dlhší čas"</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Kratší čas"</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Svietidlo je vypnuté."</string>
- <!-- no translation found for accessibility_quick_settings_flashlight_unavailable (8012811023312280810) -->
- <skip />
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Svietidlo nie je k dispozícii."</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Svietidlo je zapnuté."</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Svietidlo je vypnuté."</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Svietidlo je zapnuté."</string>
@@ -458,34 +457,23 @@
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Zapnúť Bluetooth?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Ak chcete klávesnicu pripojiť k tabletu, najprv musíte zapnúť Bluetooth."</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Zapnúť"</string>
- <!-- no translation found for show_silently (6841966539811264192) -->
- <skip />
- <!-- no translation found for block (2734508760962682611) -->
- <skip />
- <!-- no translation found for do_not_silence (6878060322594892441) -->
- <skip />
- <!-- no translation found for do_not_silence_block (4070647971382232311) -->
- <skip />
- <!-- no translation found for tuner_full_importance_settings (8103289238676424226) -->
- <skip />
+ <string name="show_silently" msgid="6841966539811264192">"Zobrazovať upozornenia bez zvukového signálu"</string>
+ <string name="block" msgid="2734508760962682611">"Blokovať všetky upozornenia"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"Nestíšiť"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"Nestíšiť ani neblokovať"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Zobraziť nastavenia vysokej dôležitosti"</string>
<string name="blocked_importance" msgid="5198578988978234161">"Zablokované"</string>
- <!-- no translation found for min_importance (1901894910809414782) -->
- <skip />
+ <string name="min_importance" msgid="1901894910809414782">"Minimálna dôležitosť"</string>
<string name="low_importance" msgid="4109929986107147930">"Nízka dôležitosť"</string>
<string name="default_importance" msgid="8192107689995742653">"Normálna dôležitosť"</string>
<string name="high_importance" msgid="1527066195614050263">"Vysoká dôležitosť"</string>
<string name="max_importance" msgid="5089005872719563894">"Neodkladná dôležitosť"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"Tieto upozornenia nikdy nezobrazovať"</string>
- <!-- no translation found for notification_importance_min (1938190340516905748) -->
- <skip />
- <!-- no translation found for notification_importance_low (3657252049508213048) -->
- <skip />
- <!-- no translation found for notification_importance_default (4466466472622442175) -->
- <skip />
- <!-- no translation found for notification_importance_high (2135428926525093825) -->
- <skip />
- <!-- no translation found for notification_importance_max (5806278962376556491) -->
- <skip />
+ <string name="notification_importance_min" msgid="1938190340516905748">"Zobrazovať v dolnej časti zoznamu upozornení bez zvukového signálu"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"Tieto upozornenia zobrazovať bez zvukového signálu"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"Umožniť týmto upozorneniam vydávať zvukové signály"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"Zobrazovať cez obrazovku a povoliť zvukový signál"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"Zobrazovať v hornej časti zoznamu upozornení, zobrazovať cez obrazovku a povoliť zvukový signál"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Ďalšie nastavenia"</string>
<string name="notification_done" msgid="5279426047273930175">"Hotovo"</string>
<string name="color_and_appearance" msgid="1254323855964993144">"Farba a vzhľad"</string>
@@ -499,7 +487,7 @@
<string name="use_dark_theme" msgid="2900938704964299312">"Použiť tmavý motív pre systém Android OS"</string>
<string name="adjust_tint" msgid="3398569573231409878">"Upraviť tónovanie"</string>
<string name="adjust_brightness" msgid="980039329808178246">"Upraviť jas"</string>
- <string name="night_mode_disclaimer" msgid="598914896926759578">"V hlavných oblastiach systému Android OS (ako sú Nastavenia), ktoré sú obyčajne zobrazené v svetlom motíve, je použitý tmavý motív."</string>
+ <string name="night_mode_disclaimer" msgid="598914896926759578">"V hlavných oblastiach systému Android OS (ako sú Nastavenia), ktoré sú obyčajne zobrazené vo svetlom motíve, je použitý tmavý motív."</string>
<string name="color_apply" msgid="9212602012641034283">"Použiť"</string>
<string name="color_revert_title" msgid="4746666545480534663">"Potvrdenie nastavení"</string>
<string name="color_revert_message" msgid="9116001069397996691">"Niektoré nastavenia farieb môžu toto zariadenie znefunkčniť. Tieto nastavenia farieb potvrdíte kliknutím na tlačidlo OK, ináč sa tieto nastavenia o 10 sekúnd obnovia."</string>
@@ -558,8 +546,7 @@
<item msgid="2139628951880142927">"Zobrazovať percentá počas nabíjania (predvolené)"</item>
<item msgid="3327323682209964956">"Nezobrazovať túto ikonu"</item>
</string-array>
- <!-- no translation found for other (4060683095962566764) -->
- <skip />
+ <string name="other" msgid="4060683095962566764">"Ďalšie"</string>
<string name="accessibility_divider" msgid="5903423481953635044">"Rozdeľovač obrazovky"</string>
<string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Posunúť nadol"</string>
<string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Posunúť nahor"</string>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index 327e553..991e9e2 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -208,8 +208,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Више времена."</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Мање времена."</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Батеријска лампа је искључена."</string>
- <!-- no translation found for accessibility_quick_settings_flashlight_unavailable (8012811023312280810) -->
- <skip />
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Лампа није доступна."</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Батеријска лампа је укључена."</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Батеријска лампа је искључена."</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Батеријска лампа је укључена."</string>
@@ -457,34 +456,23 @@
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Желите ли да укључите Bluetooth?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Да бисте повезали тастатуру са таблетом, прво морате да укључите Bluetooth."</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Укључи"</string>
- <!-- no translation found for show_silently (6841966539811264192) -->
- <skip />
- <!-- no translation found for block (2734508760962682611) -->
- <skip />
- <!-- no translation found for do_not_silence (6878060322594892441) -->
- <skip />
- <!-- no translation found for do_not_silence_block (4070647971382232311) -->
- <skip />
- <!-- no translation found for tuner_full_importance_settings (8103289238676424226) -->
- <skip />
+ <string name="show_silently" msgid="6841966539811264192">"Приказуј обавештења без звука"</string>
+ <string name="block" msgid="2734508760962682611">"Блокирај сва обавештења"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"Не искључуј звук"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"Не искључују звук нити блокирај"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Прикажи комплетна подешавања важности"</string>
<string name="blocked_importance" msgid="5198578988978234161">"Блокирана"</string>
- <!-- no translation found for min_importance (1901894910809414782) -->
- <skip />
+ <string name="min_importance" msgid="1901894910809414782">"Веома мала важност"</string>
<string name="low_importance" msgid="4109929986107147930">"Мала важност"</string>
<string name="default_importance" msgid="8192107689995742653">"Уобичајена важност"</string>
<string name="high_importance" msgid="1527066195614050263">"Велика важност"</string>
<string name="max_importance" msgid="5089005872719563894">"Важност: хитно"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"Ова обавештења се никада не приказују"</string>
- <!-- no translation found for notification_importance_min (1938190340516905748) -->
- <skip />
- <!-- no translation found for notification_importance_low (3657252049508213048) -->
- <skip />
- <!-- no translation found for notification_importance_default (4466466472622442175) -->
- <skip />
- <!-- no translation found for notification_importance_high (2135428926525093825) -->
- <skip />
- <!-- no translation found for notification_importance_max (5806278962376556491) -->
- <skip />
+ <string name="notification_importance_min" msgid="1938190340516905748">"Приказују се у дну листе обавештења без звука"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"Ова обавештења се приказују без звука"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"Дозволите да ова обавештења емитују звук"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"Накратко се приказују на екрану и емитују звук"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"Приказују се у врху листе обавештења, накратко се приказују на екрану и емитују звук"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Још подешавања"</string>
<string name="notification_done" msgid="5279426047273930175">"Готово"</string>
<string name="color_and_appearance" msgid="1254323855964993144">"Боја и изглед"</string>
@@ -557,8 +545,7 @@
<item msgid="2139628951880142927">"Прикажи проценат током пуњења (подразумевано)"</item>
<item msgid="3327323682209964956">"Не приказуј ову икону"</item>
</string-array>
- <!-- no translation found for other (4060683095962566764) -->
- <skip />
+ <string name="other" msgid="4060683095962566764">"Друго"</string>
<string name="accessibility_divider" msgid="5903423481953635044">"Разделник подељеног екрана"</string>
<string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Помери надоле"</string>
<string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Помери нагоре"</string>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index a23aba9..d35fad5 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -207,8 +207,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Längre tid."</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Kortare tid."</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Ficklampa av."</string>
- <!-- no translation found for accessibility_quick_settings_flashlight_unavailable (8012811023312280810) -->
- <skip />
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Ficklampan är inte tillgänglig."</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Ficklampa på."</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Ficklampan har inaktiverats."</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Ficklampan har aktiverats."</string>
@@ -456,34 +455,23 @@
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Vill du aktivera Bluetooth?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Om du vill ansluta tangentbordet till surfplattan måste du först aktivera Bluetooth."</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Aktivera"</string>
- <!-- no translation found for show_silently (6841966539811264192) -->
- <skip />
- <!-- no translation found for block (2734508760962682611) -->
- <skip />
- <!-- no translation found for do_not_silence (6878060322594892441) -->
- <skip />
- <!-- no translation found for do_not_silence_block (4070647971382232311) -->
- <skip />
- <!-- no translation found for tuner_full_importance_settings (8103289238676424226) -->
- <skip />
+ <string name="show_silently" msgid="6841966539811264192">"Visa aviseringar utan ljud"</string>
+ <string name="block" msgid="2734508760962682611">"Blockera alla aviseringar"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"Stäng inte av ljudet"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"Stäng inte av ljudet och blockera inte"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Visa alla relevansinställningarna"</string>
<string name="blocked_importance" msgid="5198578988978234161">"Blockerad"</string>
- <!-- no translation found for min_importance (1901894910809414782) -->
- <skip />
+ <string name="min_importance" msgid="1901894910809414782">"Oviktig avisering"</string>
<string name="low_importance" msgid="4109929986107147930">"Oviktig avisering"</string>
<string name="default_importance" msgid="8192107689995742653">"Vanlig avisering"</string>
<string name="high_importance" msgid="1527066195614050263">"Viktig avisering"</string>
<string name="max_importance" msgid="5089005872719563894">"Brådskande avisering"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"Visa aldrig de här aviseringarna"</string>
- <!-- no translation found for notification_importance_min (1938190340516905748) -->
- <skip />
- <!-- no translation found for notification_importance_low (3657252049508213048) -->
- <skip />
- <!-- no translation found for notification_importance_default (4466466472622442175) -->
- <skip />
- <!-- no translation found for notification_importance_high (2135428926525093825) -->
- <skip />
- <!-- no translation found for notification_importance_max (5806278962376556491) -->
- <skip />
+ <string name="notification_importance_min" msgid="1938190340516905748">"Visa längst ned i listan, utan ljud"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"Visa aviseringarna utan ljud"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"Tillåt ljud för de här aviseringarna"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"Visa med snabbtitt på skärmen och tillåt ljud"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"Visa högst upp i aviseringslistan och med snabbtitt på skärmen samt tillåt ljud"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Fler inställningar"</string>
<string name="notification_done" msgid="5279426047273930175">"Klar"</string>
<string name="color_and_appearance" msgid="1254323855964993144">"Färg och utseende"</string>
@@ -556,8 +544,7 @@
<item msgid="2139628951880142927">"Visa procent under laddning (standard)"</item>
<item msgid="3327323682209964956">"Visa inte den här ikonen"</item>
</string-array>
- <!-- no translation found for other (4060683095962566764) -->
- <skip />
+ <string name="other" msgid="4060683095962566764">"Annat"</string>
<string name="accessibility_divider" msgid="5903423481953635044">"Avdelare för delad skärm"</string>
<string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Flytta nedåt"</string>
<string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Flytta uppåt"</string>
diff --git a/packages/SystemUI/res/values-ta-rIN/strings.xml b/packages/SystemUI/res/values-ta-rIN/strings.xml
index 02a193a..66a1496 100644
--- a/packages/SystemUI/res/values-ta-rIN/strings.xml
+++ b/packages/SystemUI/res/values-ta-rIN/strings.xml
@@ -73,8 +73,8 @@
<string name="screenshot_saved_title" msgid="6461865960961414961">"ஸ்கிரீன் ஷாட் எடுக்கப்பட்டது."</string>
<string name="screenshot_saved_text" msgid="1152839647677558815">"உங்கள் ஸ்க்ரீன் ஷாட்டைப் பார்க்க தொடவும்."</string>
<string name="screenshot_failed_title" msgid="705781116746922771">"ஸ்க்ரீன் ஷாட்டை எடுக்க முடியவில்லை."</string>
- <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"போதுமான சேமிப்பிடம் இல்லாததால் ஸ்கிரீன் ஷாட்டைச் சேமிக்க முடியவில்லை."</string>
- <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"பயன்பாடு அல்லது உங்கள் நிறுவனம் ஸ்கிரீன் ஷாட்டுகளை எடுக்க அனுமதிக்கவில்லை."</string>
+ <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"போதுமான சேமிப்பிடம் இல்லாததால் ஸ்கிரீன்ஷாட்டைச் சேமிக்க முடியவில்லை."</string>
+ <string name="screenshot_failed_to_capture_text" msgid="7602391003979898374">"பயன்பாடு அல்லது உங்கள் நிறுவனம் ஸ்கிரீன்ஷாட்டுகளை எடுக்க அனுமதிக்கவில்லை."</string>
<string name="usb_preference_title" msgid="6551050377388882787">"USB கோப்பு இடமாற்ற விருப்பங்கள்"</string>
<string name="use_mtp_button_title" msgid="4333504413563023626">"(MTP) மீடியா பிளேயராக ஏற்று"</string>
<string name="use_ptp_button_title" msgid="7517127540301625751">"(PTP) கேமராவாக ஏற்று"</string>
@@ -306,7 +306,7 @@
<string name="recents_launch_disabled_message" msgid="1624523193008871793">"பாதுகாப்புப் பயன்முறையில் <xliff:g id="APP">%s</xliff:g> முடக்கப்பட்டது."</string>
<string name="recents_history_button_label" msgid="5153358867807604821">"வரலாறு"</string>
<string name="recents_history_clear_all_button_label" msgid="5905258334958006953">"அழி"</string>
- <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"பயன்பாடு பல சாளர அம்சத்தை ஆதரிக்காது"</string>
+ <string name="recents_drag_non_dockable_task_message" msgid="2935843902795166158">"இந்தப் பயன்பாடு பல சாளர அம்சத்தை ஆதரிக்கவில்லை"</string>
<string name="recents_launch_non_dockable_task_label" msgid="7862379814938391888">"பயன்பாடு பல சாளர அம்சத்தை ஆதரிக்காது"</string>
<string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"கிடைமட்டமாகப் பிரி"</string>
<string name="recents_multistack_add_stack_dialog_split_vertical" msgid="9075292233696180813">"செங்குத்தாகப் பிரி"</string>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index 33a07ec..9b1ea74 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -207,8 +207,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"เวลามากขึ้น"</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"เวลาน้อยลง"</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"ไฟฉายปิดอยู่"</string>
- <!-- no translation found for accessibility_quick_settings_flashlight_unavailable (8012811023312280810) -->
- <skip />
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"ไฟฉายไม่พร้อมใช้งาน"</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"ไฟฉายเปิดอยู่"</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"ปิดไฟฉายแล้ว"</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"เปิดไฟฉายแล้ว"</string>
@@ -456,34 +455,23 @@
<string name="enable_bluetooth_title" msgid="5027037706500635269">"เปิดบลูทูธไหม"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"หากต้องการเชื่อมต่อแป้นพิมพ์กับแท็บเล็ต คุณต้องเปิดบลูทูธก่อน"</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"เปิด"</string>
- <!-- no translation found for show_silently (6841966539811264192) -->
- <skip />
- <!-- no translation found for block (2734508760962682611) -->
- <skip />
- <!-- no translation found for do_not_silence (6878060322594892441) -->
- <skip />
- <!-- no translation found for do_not_silence_block (4070647971382232311) -->
- <skip />
- <!-- no translation found for tuner_full_importance_settings (8103289238676424226) -->
- <skip />
+ <string name="show_silently" msgid="6841966539811264192">"แสดงการแจ้งเตือนโดยไม่ส่งเสียง"</string>
+ <string name="block" msgid="2734508760962682611">"บล็อกการแจ้งเตือนทั้งหมด"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"ไม่ปิดเสียง"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"ไม่ปิดเสียงหรือบล็อก"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"แสดงการตั้งค่าความสำคัญแบบเต็ม"</string>
<string name="blocked_importance" msgid="5198578988978234161">"บล็อกแล้ว"</string>
- <!-- no translation found for min_importance (1901894910809414782) -->
- <skip />
+ <string name="min_importance" msgid="1901894910809414782">"ความสำคัญน้อย"</string>
<string name="low_importance" msgid="4109929986107147930">"ความสำคัญต่ำ"</string>
<string name="default_importance" msgid="8192107689995742653">"ความสำคัญปกติ"</string>
<string name="high_importance" msgid="1527066195614050263">"ความสำคัญสูง"</string>
<string name="max_importance" msgid="5089005872719563894">"ความสำคัญเร่งด่วน"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"ไม่ต้องแสดงการแจ้งเตือนเหล่านี้"</string>
- <!-- no translation found for notification_importance_min (1938190340516905748) -->
- <skip />
- <!-- no translation found for notification_importance_low (3657252049508213048) -->
- <skip />
- <!-- no translation found for notification_importance_default (4466466472622442175) -->
- <skip />
- <!-- no translation found for notification_importance_high (2135428926525093825) -->
- <skip />
- <!-- no translation found for notification_importance_max (5806278962376556491) -->
- <skip />
+ <string name="notification_importance_min" msgid="1938190340516905748">"แสดงที่ด้านล่างของรายการแจ้งเตือนโดยไม่ส่งเสียง"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"แสดงการแจ้งเตือนเหล่านี้โดยไม่ส่งเสียง"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"ให้การแจ้งเตือนเหล่านี้ส่งเสียงได้"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"แสดงบนหน้าจอและให้ส่งเสียงได้"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"แสดงที่ด้านบนของรายการการแจ้งเตือน แสดงบนหน้าจอและให้ส่งเสียงได้"</string>
<string name="notification_more_settings" msgid="816306283396553571">"การตั้งค่าเพิ่มเติม"</string>
<string name="notification_done" msgid="5279426047273930175">"เสร็จสิ้น"</string>
<string name="color_and_appearance" msgid="1254323855964993144">"สีและลักษณะที่ปรากฏ"</string>
@@ -556,8 +544,7 @@
<item msgid="2139628951880142927">"แสดงเปอร์เซ็นต์เมื่อชาร์จ (ค่าเริ่มต้น)"</item>
<item msgid="3327323682209964956">"อย่าแสดงไอคอนนี้"</item>
</string-array>
- <!-- no translation found for other (4060683095962566764) -->
- <skip />
+ <string name="other" msgid="4060683095962566764">"อื่นๆ"</string>
<string name="accessibility_divider" msgid="5903423481953635044">"เส้นแบ่งหน้าจอ"</string>
<string name="accessibility_action_divider_move_down" msgid="704893304141890042">"เลื่อนลง"</string>
<string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"เลื่อนขึ้น"</string>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index 99fa7a2..d131c84 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -207,8 +207,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Higit pang oras."</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Mas kaunting oras."</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Naka-off ang flashlight."</string>
- <!-- no translation found for accessibility_quick_settings_flashlight_unavailable (8012811023312280810) -->
- <skip />
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Hindi available ang flashlight."</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Naka-on ang flashlight."</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Na-off ang flashlight."</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Na-on ang flashlight."</string>
@@ -456,34 +455,23 @@
<string name="enable_bluetooth_title" msgid="5027037706500635269">"I-on ang Bluetooth?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Upang ikonekta ang iyong keyboard sa iyong tablet, kailangan mo munang i-on ang Bluetooth."</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"I-on"</string>
- <!-- no translation found for show_silently (6841966539811264192) -->
- <skip />
- <!-- no translation found for block (2734508760962682611) -->
- <skip />
- <!-- no translation found for do_not_silence (6878060322594892441) -->
- <skip />
- <!-- no translation found for do_not_silence_block (4070647971382232311) -->
- <skip />
- <!-- no translation found for tuner_full_importance_settings (8103289238676424226) -->
- <skip />
+ <string name="show_silently" msgid="6841966539811264192">"Tahimik na ipakita ang mga notification"</string>
+ <string name="block" msgid="2734508760962682611">"I-block ang lahat ng notification"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"Huwag i-silent"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"Huwag i-silent o i-block"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Ipakita ang kumpletong mga setting ng kahalagahan"</string>
<string name="blocked_importance" msgid="5198578988978234161">"Na-block"</string>
- <!-- no translation found for min_importance (1901894910809414782) -->
- <skip />
+ <string name="min_importance" msgid="1901894910809414782">"Hindi masyadong mahalaga"</string>
<string name="low_importance" msgid="4109929986107147930">"Hindi masyadong mahalaga"</string>
<string name="default_importance" msgid="8192107689995742653">"Mahalaga"</string>
<string name="high_importance" msgid="1527066195614050263">"Napakahalaga"</string>
<string name="max_importance" msgid="5089005872719563894">"Mahalagang-mahalaga"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"Huwag kailanman ipakita ang mga notification na ito"</string>
- <!-- no translation found for notification_importance_min (1938190340516905748) -->
- <skip />
- <!-- no translation found for notification_importance_low (3657252049508213048) -->
- <skip />
- <!-- no translation found for notification_importance_default (4466466472622442175) -->
- <skip />
- <!-- no translation found for notification_importance_high (2135428926525093825) -->
- <skip />
- <!-- no translation found for notification_importance_max (5806278962376556491) -->
- <skip />
+ <string name="notification_importance_min" msgid="1938190340516905748">"Tahimik na ipakita sa ibaba ng listahan ng notification"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"Tahimik na ipakita ang mga notification na ito"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"Payagan ang mga notification na ito na tumunog"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"Palitawin sa screen at payagang tumunog"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"Ipakita sa itaas ng listahan ng mga notification, palitawin sa screen at payagang tumunog"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Higit pang mga setting"</string>
<string name="notification_done" msgid="5279426047273930175">"Tapos Na"</string>
<string name="color_and_appearance" msgid="1254323855964993144">"Kulay at hitsura"</string>
@@ -556,8 +544,7 @@
<item msgid="2139628951880142927">"Ipakita ang porsyento kapag nagcha-charge (default)"</item>
<item msgid="3327323682209964956">"Huwag ipakita ang icon na ito"</item>
</string-array>
- <!-- no translation found for other (4060683095962566764) -->
- <skip />
+ <string name="other" msgid="4060683095962566764">"Iba pa"</string>
<string name="accessibility_divider" msgid="5903423481953635044">"Divider ng split-screen"</string>
<string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Ilipat pababa"</string>
<string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Ilipat pataas"</string>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index 050f1f7..fd9e14c 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -207,8 +207,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Daha uzun süre."</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Daha kısa süre."</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"El feneri kapalı."</string>
- <!-- no translation found for accessibility_quick_settings_flashlight_unavailable (8012811023312280810) -->
- <skip />
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"El feneri kullanılamıyor."</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"El feneri açık."</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"El feneri kapatıldı."</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"El feneri açıldı."</string>
@@ -456,34 +455,23 @@
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Bluetooth açılsın mı?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Klavyenizi tabletinize bağlamak için önce Bluetooth\'u açmanız gerekir."</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Aç"</string>
- <!-- no translation found for show_silently (6841966539811264192) -->
- <skip />
- <!-- no translation found for block (2734508760962682611) -->
- <skip />
- <!-- no translation found for do_not_silence (6878060322594892441) -->
- <skip />
- <!-- no translation found for do_not_silence_block (4070647971382232311) -->
- <skip />
- <!-- no translation found for tuner_full_importance_settings (8103289238676424226) -->
- <skip />
+ <string name="show_silently" msgid="6841966539811264192">"Bildirimleri sessizce göster"</string>
+ <string name="block" msgid="2734508760962682611">"Tüm bildirimleri engelle"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"Sessiz moda alma"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"Sessiz moda alma veya engelleme"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Tüm önem ayarlarını göster"</string>
<string name="blocked_importance" msgid="5198578988978234161">"Engellendi"</string>
- <!-- no translation found for min_importance (1901894910809414782) -->
- <skip />
+ <string name="min_importance" msgid="1901894910809414782">"Önemi en düşük"</string>
<string name="low_importance" msgid="4109929986107147930">"Önem düzeyi düşük"</string>
<string name="default_importance" msgid="8192107689995742653">"Önem düzeyi normal"</string>
<string name="high_importance" msgid="1527066195614050263">"Önem düzeyi yüksek"</string>
<string name="max_importance" msgid="5089005872719563894">"Önem düzeyi acil"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"Bu bildirimleri hiçbir zaman gösterme"</string>
- <!-- no translation found for notification_importance_min (1938190340516905748) -->
- <skip />
- <!-- no translation found for notification_importance_low (3657252049508213048) -->
- <skip />
- <!-- no translation found for notification_importance_default (4466466472622442175) -->
- <skip />
- <!-- no translation found for notification_importance_high (2135428926525093825) -->
- <skip />
- <!-- no translation found for notification_importance_max (5806278962376556491) -->
- <skip />
+ <string name="notification_importance_min" msgid="1938190340516905748">"Bildirim listesinin en altında sessizce göster"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"Bu bildirimleri sessizce göster"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"Bu bildirimlerin ses çıkarmasına izin ver"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"Ekrana getir ve sesli bildirime izin ver"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"Bildirim listesinin üstünde göster, ekrana getir ve sesli bildirime izin ver"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Diğer ayarlar"</string>
<string name="notification_done" msgid="5279426047273930175">"Bitti"</string>
<string name="color_and_appearance" msgid="1254323855964993144">"Renk ve görünüm"</string>
@@ -556,8 +544,7 @@
<item msgid="2139628951880142927">"Şarj olurken yüzdeyi göster (varsayılan)"</item>
<item msgid="3327323682209964956">"Bu simgeyi gösterme"</item>
</string-array>
- <!-- no translation found for other (4060683095962566764) -->
- <skip />
+ <string name="other" msgid="4060683095962566764">"Diğer"</string>
<string name="accessibility_divider" msgid="5903423481953635044">"Bölünmüş ekran ayırıcı"</string>
<string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Aşağı taşı"</string>
<string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Yukarı taşı"</string>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index 485e2b2..e5bf06d 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -209,8 +209,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Більше часу."</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Менше часу."</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Ліхтарик вимк."</string>
- <!-- no translation found for accessibility_quick_settings_flashlight_unavailable (8012811023312280810) -->
- <skip />
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Ліхтарик недоступний."</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Ліхтарик увімк."</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Ліхтарик вимкнено."</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Ліхтарик увімкнено."</string>
@@ -458,34 +457,23 @@
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Увімкнути Bluetooth?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Щоб під’єднати клавіатуру до планшета, спершу потрібно ввімкнути Bluetooth."</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Увімкнути"</string>
- <!-- no translation found for show_silently (6841966539811264192) -->
- <skip />
- <!-- no translation found for block (2734508760962682611) -->
- <skip />
- <!-- no translation found for do_not_silence (6878060322594892441) -->
- <skip />
- <!-- no translation found for do_not_silence_block (4070647971382232311) -->
- <skip />
- <!-- no translation found for tuner_full_importance_settings (8103289238676424226) -->
- <skip />
+ <string name="show_silently" msgid="6841966539811264192">"Показувати сповіщення без звукового сигналу"</string>
+ <string name="block" msgid="2734508760962682611">"Блокувати всі сповіщення"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"Не вимикати звуковий сигнал"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"Не вимикати звуковий сигнал і не блокувати"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Показати налаштування пріоритетності"</string>
<string name="blocked_importance" msgid="5198578988978234161">"Заблоковано"</string>
- <!-- no translation found for min_importance (1901894910809414782) -->
- <skip />
+ <string name="min_importance" msgid="1901894910809414782">"Низький пріоритет"</string>
<string name="low_importance" msgid="4109929986107147930">"Низький пріоритет"</string>
<string name="default_importance" msgid="8192107689995742653">"Стандартний пріоритет"</string>
<string name="high_importance" msgid="1527066195614050263">"Високий пріоритет"</string>
<string name="max_importance" msgid="5089005872719563894">"Терміново"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"Ніколи не показувати ці сповіщення"</string>
- <!-- no translation found for notification_importance_min (1938190340516905748) -->
- <skip />
- <!-- no translation found for notification_importance_low (3657252049508213048) -->
- <skip />
- <!-- no translation found for notification_importance_default (4466466472622442175) -->
- <skip />
- <!-- no translation found for notification_importance_high (2135428926525093825) -->
- <skip />
- <!-- no translation found for notification_importance_max (5806278962376556491) -->
- <skip />
+ <string name="notification_importance_min" msgid="1938190340516905748">"Показувати сповіщення внизу списку без звукового сигналу"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"Показувати ці сповіщення без звукового сигналу"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"Увімкнути звуковий сигнал для цих сповіщень"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"Показувати сповіщення на екрані зі звуковим сигналом"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"Показувати сповіщення вгорі списку, на екрані та зі звуковим сигналом"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Більше налаштувань"</string>
<string name="notification_done" msgid="5279426047273930175">"Готово"</string>
<string name="color_and_appearance" msgid="1254323855964993144">"Колір і вигляд"</string>
@@ -558,8 +546,7 @@
<item msgid="2139628951880142927">"Показувати відсотки під час заряджання (за умовчанням)"</item>
<item msgid="3327323682209964956">"Не показувати цей значок"</item>
</string-array>
- <!-- no translation found for other (4060683095962566764) -->
- <skip />
+ <string name="other" msgid="4060683095962566764">"Інше"</string>
<string name="accessibility_divider" msgid="5903423481953635044">"Розділювач екрана"</string>
<string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Перемістити вниз"</string>
<string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Перемістити вгору"</string>
diff --git a/packages/SystemUI/res/values-ur-rPK/strings.xml b/packages/SystemUI/res/values-ur-rPK/strings.xml
index 20a2a6f..7a10732 100644
--- a/packages/SystemUI/res/values-ur-rPK/strings.xml
+++ b/packages/SystemUI/res/values-ur-rPK/strings.xml
@@ -207,8 +207,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"مزید وقت۔"</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"کم وقت۔"</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"فلیش لائٹ آف ہے۔"</string>
- <!-- no translation found for accessibility_quick_settings_flashlight_unavailable (8012811023312280810) -->
- <skip />
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"فلیش لائٹ دستیاب نہیں ہے"</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"فلیش لائٹ آن ہے۔"</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"فلیش لائٹ کو آف کر دیا گیا۔"</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"فلیش لائٹ کو آن کر دیا گیا۔"</string>
@@ -456,34 +455,23 @@
<string name="enable_bluetooth_title" msgid="5027037706500635269">"بلوٹوتھ آن کریں؟"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"اپنے کی بورڈ کو اپنے ٹیبلٹ کے ساتھ منسلک کرنے کیلئے پہلے آپ کو اپنا بلو ٹوتھ آن کرنا ہو گا۔"</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"آن کریں"</string>
- <!-- no translation found for show_silently (6841966539811264192) -->
- <skip />
- <!-- no translation found for block (2734508760962682611) -->
- <skip />
- <!-- no translation found for do_not_silence (6878060322594892441) -->
- <skip />
- <!-- no translation found for do_not_silence_block (4070647971382232311) -->
- <skip />
- <!-- no translation found for tuner_full_importance_settings (8103289238676424226) -->
- <skip />
+ <string name="show_silently" msgid="6841966539811264192">"اطلاعات خاموشی سے دکھائیں"</string>
+ <string name="block" msgid="2734508760962682611">"تمام اطلاعات کو مسدود کریں"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"خاموش نہ کریں"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"خاموش یا مسدود نہ کریں"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"اہمیت کی پوری ترتیبات دکھائیں"</string>
<string name="blocked_importance" msgid="5198578988978234161">"مسدود کردہ"</string>
- <!-- no translation found for min_importance (1901894910809414782) -->
- <skip />
+ <string name="min_importance" msgid="1901894910809414782">"کم سے کم اہمیت"</string>
<string name="low_importance" msgid="4109929986107147930">"کم اہمیت"</string>
<string name="default_importance" msgid="8192107689995742653">"عمومی اہمیت"</string>
<string name="high_importance" msgid="1527066195614050263">"زیادہ اہمیت"</string>
<string name="max_importance" msgid="5089005872719563894">"فوری اہمیت"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"یہ اطلاعات کبھی مت دکھائیں"</string>
- <!-- no translation found for notification_importance_min (1938190340516905748) -->
- <skip />
- <!-- no translation found for notification_importance_low (3657252049508213048) -->
- <skip />
- <!-- no translation found for notification_importance_default (4466466472622442175) -->
- <skip />
- <!-- no translation found for notification_importance_high (2135428926525093825) -->
- <skip />
- <!-- no translation found for notification_importance_max (5806278962376556491) -->
- <skip />
+ <string name="notification_importance_min" msgid="1938190340516905748">"اطلاعات کی فہرست کے سب سے نیچے خاموشی سے دکھائیں"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"خاموشی سے یہ اطلاعات دکھائیں"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"ان اطلاعات کو آواز نکالنے کی اجازت دیں"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"اسکرین پر دکھائیں اور آواز کی اجازت دیں"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"اطلاعات کی فہرست پر سب سے اوپر دکھائیں، اسکرین پر دکھائیں اور آواز کی اجازت دیں"</string>
<string name="notification_more_settings" msgid="816306283396553571">"مزید ترتیبات"</string>
<string name="notification_done" msgid="5279426047273930175">"ہوگیا"</string>
<string name="color_and_appearance" msgid="1254323855964993144">"رنگ اور ظہور"</string>
@@ -556,8 +544,7 @@
<item msgid="2139628951880142927">"چارج ہوتے وقت فیصد دکھائیں (ڈیفالٹ)"</item>
<item msgid="3327323682209964956">"یہ آئیکن نہ دکھائیں"</item>
</string-array>
- <!-- no translation found for other (4060683095962566764) -->
- <skip />
+ <string name="other" msgid="4060683095962566764">"دیگر"</string>
<string name="accessibility_divider" msgid="5903423481953635044">"سپلٹ اسکرین تقسیم کار"</string>
<string name="accessibility_action_divider_move_down" msgid="704893304141890042">"نیچے منتقل کریں"</string>
<string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"اوپر منتقل کریں"</string>
diff --git a/packages/SystemUI/res/values-uz-rUZ/strings.xml b/packages/SystemUI/res/values-uz-rUZ/strings.xml
index 3fc7aad..79729dc 100644
--- a/packages/SystemUI/res/values-uz-rUZ/strings.xml
+++ b/packages/SystemUI/res/values-uz-rUZ/strings.xml
@@ -207,8 +207,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Ko‘proq vaqt."</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Kamroq vaqt."</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"Fonar o‘chirilgan."</string>
- <!-- no translation found for accessibility_quick_settings_flashlight_unavailable (8012811023312280810) -->
- <skip />
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"Bu yerda fonar yo‘q."</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"Fonar yoqilgan."</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"Fonar o‘chirildi."</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"Fonar yoqildi."</string>
@@ -456,34 +455,23 @@
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Bluetooth yoqilsinmi?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Klaviaturani planshetingizga ulash uchun Bluetooth xizmatini yoqishingiz kerak."</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Yoqish"</string>
- <!-- no translation found for show_silently (6841966539811264192) -->
- <skip />
- <!-- no translation found for block (2734508760962682611) -->
- <skip />
- <!-- no translation found for do_not_silence (6878060322594892441) -->
- <skip />
- <!-- no translation found for do_not_silence_block (4070647971382232311) -->
- <skip />
- <!-- no translation found for tuner_full_importance_settings (8103289238676424226) -->
- <skip />
+ <string name="show_silently" msgid="6841966539811264192">"Bildirishnomalar ovozsiz ko‘rsatilsin"</string>
+ <string name="block" msgid="2734508760962682611">"Barcha bildirishnomalar bloklansin"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"Ovozi o‘chirilmasin"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"Ovozi o‘chirilmasin yoki bloklanmasin"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Barcha muhimlik sozlamalarini ko‘rsatish"</string>
<string name="blocked_importance" msgid="5198578988978234161">"Bloklangan"</string>
- <!-- no translation found for min_importance (1901894910809414782) -->
- <skip />
+ <string name="min_importance" msgid="1901894910809414782">"Kamroq muhim"</string>
<string name="low_importance" msgid="4109929986107147930">"Kamroq muhim"</string>
<string name="default_importance" msgid="8192107689995742653">"O‘rtacha muhim"</string>
<string name="high_importance" msgid="1527066195614050263">"Juda muhim"</string>
<string name="max_importance" msgid="5089005872719563894">"Favqulodda muhim"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"Bu bildirishnomalar boshqa ko‘rsatilmasin"</string>
- <!-- no translation found for notification_importance_min (1938190340516905748) -->
- <skip />
- <!-- no translation found for notification_importance_low (3657252049508213048) -->
- <skip />
- <!-- no translation found for notification_importance_default (4466466472622442175) -->
- <skip />
- <!-- no translation found for notification_importance_high (2135428926525093825) -->
- <skip />
- <!-- no translation found for notification_importance_max (5806278962376556491) -->
- <skip />
+ <string name="notification_importance_min" msgid="1938190340516905748">"Bildirishnomalar ro‘yxatining oxirida ovozsiz ko‘rsatilsin"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"Bu bildirishnomalar ovozsiz ko‘rsatilsin"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"Bu bildirishnomalar ovoz bilan ko‘rsatilsin"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"Barcha oynalar ustida ovoz bilan ko‘rsatilsin"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"Bildirishnomalar ro‘yxatining boshida va barcha oynalar ustida ovoz bilan ko‘rsatilsin"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Boshqa sozlamalar"</string>
<string name="notification_done" msgid="5279426047273930175">"Tayyor"</string>
<string name="color_and_appearance" msgid="1254323855964993144">"Rang va ko‘rinishi"</string>
@@ -497,7 +485,7 @@
<string name="use_dark_theme" msgid="2900938704964299312">"Android uchun to‘q rangli mavzudan foydalanish"</string>
<string name="adjust_tint" msgid="3398569573231409878">"Rang tusini o‘zgartirish"</string>
<string name="adjust_brightness" msgid="980039329808178246">"Yorqinlikni o‘zgartirish"</string>
- <string name="night_mode_disclaimer" msgid="598914896926759578">"To‘q rangli mavzu Android OS’ning o‘zak sahifalariga ham qo‘llaniladi va bu Sozlamalar kabi och rangli mavzularda odatdagiday ko‘rsatiladi."</string>
+ <string name="night_mode_disclaimer" msgid="598914896926759578">"To‘q rangli mavzu Android tizimining odatda och rangda ko‘rsatiladigan o‘zak sahifalariga (masalan, Sozlamalar) nisbatan qo‘llaniladi."</string>
<string name="color_apply" msgid="9212602012641034283">"Qo‘llash"</string>
<string name="color_revert_title" msgid="4746666545480534663">"Sozlamalarni tasdiqlang"</string>
<string name="color_revert_message" msgid="9116001069397996691">"Ba’zi rang sozlamalari qurilmadan foydalanishni qiyinlashtirish mumkin. Tanlgan parametrlarni tasdiqlash uchun “OK” tugmasini bosing. Aks holda, ular 10 soniyadan so‘ng qayta tiklanadi."</string>
@@ -556,9 +544,8 @@
<item msgid="2139628951880142927">"Quvvat olayotganda foizda ko‘rsatilsin (birlamchi)"</item>
<item msgid="3327323682209964956">"Bu belgi boshqa ko‘rsatilmasin"</item>
</string-array>
- <!-- no translation found for other (4060683095962566764) -->
- <skip />
- <string name="accessibility_divider" msgid="5903423481953635044">"Ekranni ikkiga bo‘lgich"</string>
+ <string name="other" msgid="4060683095962566764">"Boshqa"</string>
+ <string name="accessibility_divider" msgid="5903423481953635044">"Ekranni ikkiga bo‘lish chizig‘i"</string>
<string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Pastga siljitish"</string>
<string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Tepaga siljitish"</string>
<string name="accessibility_action_divider_move_left" msgid="9218189832115847253">"Chapga siljitish"</string>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index d48a9e6..f828306 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -207,8 +207,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"延长时间。"</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"缩短时间。"</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"手电筒关闭。"</string>
- <!-- no translation found for accessibility_quick_settings_flashlight_unavailable (8012811023312280810) -->
- <skip />
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"无法使用手电筒。"</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"手电筒打开。"</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"手电筒已关闭。"</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"手电筒已打开。"</string>
@@ -456,34 +455,23 @@
<string name="enable_bluetooth_title" msgid="5027037706500635269">"要开启蓝牙吗?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"要将您的键盘连接到平板电脑,您必须先开启蓝牙。"</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"开启"</string>
- <!-- no translation found for show_silently (6841966539811264192) -->
- <skip />
- <!-- no translation found for block (2734508760962682611) -->
- <skip />
- <!-- no translation found for do_not_silence (6878060322594892441) -->
- <skip />
- <!-- no translation found for do_not_silence_block (4070647971382232311) -->
- <skip />
- <!-- no translation found for tuner_full_importance_settings (8103289238676424226) -->
- <skip />
+ <string name="show_silently" msgid="6841966539811264192">"显示通知,但不发出提示音"</string>
+ <string name="block" msgid="2734508760962682611">"屏蔽所有通知"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"不静音"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"不静音或不屏蔽"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"显示完整的重要性设置"</string>
<string name="blocked_importance" msgid="5198578988978234161">"屏蔽"</string>
- <!-- no translation found for min_importance (1901894910809414782) -->
- <skip />
+ <string name="min_importance" msgid="1901894910809414782">"最低重要性"</string>
<string name="low_importance" msgid="4109929986107147930">"重要性:低"</string>
<string name="default_importance" msgid="8192107689995742653">"重要性:一般"</string>
<string name="high_importance" msgid="1527066195614050263">"重要性:高"</string>
<string name="max_importance" msgid="5089005872719563894">"重要性:紧急"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"一律不显示这些通知"</string>
- <!-- no translation found for notification_importance_min (1938190340516905748) -->
- <skip />
- <!-- no translation found for notification_importance_low (3657252049508213048) -->
- <skip />
- <!-- no translation found for notification_importance_default (4466466472622442175) -->
- <skip />
- <!-- no translation found for notification_importance_high (2135428926525093825) -->
- <skip />
- <!-- no translation found for notification_importance_max (5806278962376556491) -->
- <skip />
+ <string name="notification_importance_min" msgid="1938190340516905748">"在通知列表底部显示,但不发出提示音"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"显示这些通知,但不发出提示音"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"允许这些通知发出提示音"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"在屏幕上短暂显示,并发出提示音"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"在通知列表顶部显示,同时在屏幕上短暂显示,并发出提示音"</string>
<string name="notification_more_settings" msgid="816306283396553571">"更多设置"</string>
<string name="notification_done" msgid="5279426047273930175">"完成"</string>
<string name="color_and_appearance" msgid="1254323855964993144">"颜色和外观"</string>
@@ -556,8 +544,7 @@
<item msgid="2139628951880142927">"充电时显示百分比(默认)"</item>
<item msgid="3327323682209964956">"不显示此图标"</item>
</string-array>
- <!-- no translation found for other (4060683095962566764) -->
- <skip />
+ <string name="other" msgid="4060683095962566764">"其他"</string>
<string name="accessibility_divider" msgid="5903423481953635044">"分屏分隔线"</string>
<string name="accessibility_action_divider_move_down" msgid="704893304141890042">"下移"</string>
<string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"上移"</string>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index 609f94d..bd379b7 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -207,8 +207,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"增加時間。"</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"減少時間。"</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"閃光燈已關閉。"</string>
- <!-- no translation found for accessibility_quick_settings_flashlight_unavailable (8012811023312280810) -->
- <skip />
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"無法使用手電筒。"</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"閃光燈已開啟。"</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"閃光燈已關閉。"</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"閃光燈已開啟。"</string>
@@ -456,34 +455,23 @@
<string name="enable_bluetooth_title" msgid="5027037706500635269">"要開啟藍牙嗎?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"如要將鍵盤連接至平板電腦,請先開啟藍牙。"</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"開啟"</string>
- <!-- no translation found for show_silently (6841966539811264192) -->
- <skip />
- <!-- no translation found for block (2734508760962682611) -->
- <skip />
- <!-- no translation found for do_not_silence (6878060322594892441) -->
- <skip />
- <!-- no translation found for do_not_silence_block (4070647971382232311) -->
- <skip />
- <!-- no translation found for tuner_full_importance_settings (8103289238676424226) -->
- <skip />
+ <string name="show_silently" msgid="6841966539811264192">"顯示通知,但不發出音效"</string>
+ <string name="block" msgid="2734508760962682611">"封鎖所有通知"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"不設為靜音"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"不設為靜音或封鎖"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"顯示所有重要性設定"</string>
<string name="blocked_importance" msgid="5198578988978234161">"已封鎖"</string>
- <!-- no translation found for min_importance (1901894910809414782) -->
- <skip />
+ <string name="min_importance" msgid="1901894910809414782">"最低重要性"</string>
<string name="low_importance" msgid="4109929986107147930">"低重要性"</string>
<string name="default_importance" msgid="8192107689995742653">"一般重要性"</string>
<string name="high_importance" msgid="1527066195614050263">"高重要性"</string>
<string name="max_importance" msgid="5089005872719563894">"緊急重要性"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"永不顯示這些通知"</string>
- <!-- no translation found for notification_importance_min (1938190340516905748) -->
- <skip />
- <!-- no translation found for notification_importance_low (3657252049508213048) -->
- <skip />
- <!-- no translation found for notification_importance_default (4466466472622442175) -->
- <skip />
- <!-- no translation found for notification_importance_high (2135428926525093825) -->
- <skip />
- <!-- no translation found for notification_importance_max (5806278962376556491) -->
- <skip />
+ <string name="notification_importance_min" msgid="1938190340516905748">"在通知清單底部顯示但不發出音效"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"顯示這些通知但不發出音效"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"允許這些通知發出音效"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"不時於螢幕出現並發出音效"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"在通知清單頂部顯示,並不時於螢幕出現及發出音效"</string>
<string name="notification_more_settings" msgid="816306283396553571">"更多設定"</string>
<string name="notification_done" msgid="5279426047273930175">"完成"</string>
<string name="color_and_appearance" msgid="1254323855964993144">"顏色和外觀"</string>
@@ -556,8 +544,7 @@
<item msgid="2139628951880142927">"充電時顯示百分比 (預設)"</item>
<item msgid="3327323682209964956">"不顯示這個圖示"</item>
</string-array>
- <!-- no translation found for other (4060683095962566764) -->
- <skip />
+ <string name="other" msgid="4060683095962566764">"其他"</string>
<string name="accessibility_divider" msgid="5903423481953635044">"分割畫面分隔線"</string>
<string name="accessibility_action_divider_move_down" msgid="704893304141890042">"向下移"</string>
<string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"向上移"</string>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index 2188c3c..d580b28 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -207,8 +207,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"增加時間。"</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"減少時間。"</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"閃光燈已關閉。"</string>
- <!-- no translation found for accessibility_quick_settings_flashlight_unavailable (8012811023312280810) -->
- <skip />
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"無法使用手電筒。"</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"閃光燈已開啟。"</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"閃光燈已關閉。"</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"閃光燈已開啟。"</string>
@@ -456,34 +455,23 @@
<string name="enable_bluetooth_title" msgid="5027037706500635269">"要開啟藍牙功能嗎?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"如要將鍵盤連線到平板電腦,您必須先開啟藍牙。"</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"開啟"</string>
- <!-- no translation found for show_silently (6841966539811264192) -->
- <skip />
- <!-- no translation found for block (2734508760962682611) -->
- <skip />
- <!-- no translation found for do_not_silence (6878060322594892441) -->
- <skip />
- <!-- no translation found for do_not_silence_block (4070647971382232311) -->
- <skip />
- <!-- no translation found for tuner_full_importance_settings (8103289238676424226) -->
- <skip />
+ <string name="show_silently" msgid="6841966539811264192">"顯示通知,但不發出任何音效"</string>
+ <string name="block" msgid="2734508760962682611">"封鎖所有通知"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"不設定靜音"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"不設定靜音或封鎖"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"顯示完整的重要性設定"</string>
<string name="blocked_importance" msgid="5198578988978234161">"封鎖"</string>
- <!-- no translation found for min_importance (1901894910809414782) -->
- <skip />
+ <string name="min_importance" msgid="1901894910809414782">"最低重要性"</string>
<string name="low_importance" msgid="4109929986107147930">"低重要性"</string>
<string name="default_importance" msgid="8192107689995742653">"一般重要性"</string>
<string name="high_importance" msgid="1527066195614050263">"高重要性"</string>
<string name="max_importance" msgid="5089005872719563894">"緊急重要性"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"一律不顯示這些通知"</string>
- <!-- no translation found for notification_importance_min (1938190340516905748) -->
- <skip />
- <!-- no translation found for notification_importance_low (3657252049508213048) -->
- <skip />
- <!-- no translation found for notification_importance_default (4466466472622442175) -->
- <skip />
- <!-- no translation found for notification_importance_high (2135428926525093825) -->
- <skip />
- <!-- no translation found for notification_importance_max (5806278962376556491) -->
- <skip />
+ <string name="notification_importance_min" msgid="1938190340516905748">"顯示在通知清單底端,但不發出任何音效"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"顯示這些通知,但不發出任何音效"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"允許這些通知發出音效"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"短暫顯示在畫面上並發出音效"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"顯示在通知清單頂端,同時短暫顯示在畫面上並發出音效"</string>
<string name="notification_more_settings" msgid="816306283396553571">"更多設定"</string>
<string name="notification_done" msgid="5279426047273930175">"完成"</string>
<string name="color_and_appearance" msgid="1254323855964993144">"顏色和外觀"</string>
@@ -556,8 +544,7 @@
<item msgid="2139628951880142927">"充電時顯示百分比 (預設)"</item>
<item msgid="3327323682209964956">"不顯示這個圖示"</item>
</string-array>
- <!-- no translation found for other (4060683095962566764) -->
- <skip />
+ <string name="other" msgid="4060683095962566764">"其他"</string>
<string name="accessibility_divider" msgid="5903423481953635044">"分割畫面分隔線"</string>
<string name="accessibility_action_divider_move_down" msgid="704893304141890042">"向下移"</string>
<string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"向上移"</string>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index 69c85ab..9382b26 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -207,8 +207,7 @@
<string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Isikhathi esiningi."</string>
<string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"Isikhathi esincane."</string>
<string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"I-Flashlight ivaliwe."</string>
- <!-- no translation found for accessibility_quick_settings_flashlight_unavailable (8012811023312280810) -->
- <skip />
+ <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"I-Flashlight ayitholakali."</string>
<string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"I-Flashlight ivuliwe."</string>
<string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"I-Flashlight ivaliwe."</string>
<string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"I-Flashlight ivuliwe."</string>
@@ -456,34 +455,23 @@
<string name="enable_bluetooth_title" msgid="5027037706500635269">"Vula i-Bluetooth?"</string>
<string name="enable_bluetooth_message" msgid="9106595990708985385">"Ukuze uxhume ikhibhodi yakho nethebhulethi yakho, kufanele uqale ngokuvula i-Bluetooth."</string>
<string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"Vula"</string>
- <!-- no translation found for show_silently (6841966539811264192) -->
- <skip />
- <!-- no translation found for block (2734508760962682611) -->
- <skip />
- <!-- no translation found for do_not_silence (6878060322594892441) -->
- <skip />
- <!-- no translation found for do_not_silence_block (4070647971382232311) -->
- <skip />
- <!-- no translation found for tuner_full_importance_settings (8103289238676424226) -->
- <skip />
+ <string name="show_silently" msgid="6841966539811264192">"Bonisa izaziso ngokuthulile"</string>
+ <string name="block" msgid="2734508760962682611">"Vimbela zonke izaziso"</string>
+ <string name="do_not_silence" msgid="6878060322594892441">"Ungathulisi"</string>
+ <string name="do_not_silence_block" msgid="4070647971382232311">"Ungathulisi noma uvimbele"</string>
+ <string name="tuner_full_importance_settings" msgid="8103289238676424226">"Bonisa izilungiselelo ezibalulekile ezigcwele"</string>
<string name="blocked_importance" msgid="5198578988978234161">"Kuvinjelwe"</string>
- <!-- no translation found for min_importance (1901894910809414782) -->
- <skip />
+ <string name="min_importance" msgid="1901894910809414782">"Okubaluleke kancane"</string>
<string name="low_importance" msgid="4109929986107147930">"Ukubaluleka okuphansi"</string>
<string name="default_importance" msgid="8192107689995742653">"Ukubaluleka okujwayelekile"</string>
<string name="high_importance" msgid="1527066195614050263">"Ukubaluleka okuphezulu"</string>
<string name="max_importance" msgid="5089005872719563894">"Ukubaluleka okusheshayo"</string>
<string name="notification_importance_blocked" msgid="2397192642657872872">"Ungalokothi ubonise lezi zaziso"</string>
- <!-- no translation found for notification_importance_min (1938190340516905748) -->
- <skip />
- <!-- no translation found for notification_importance_low (3657252049508213048) -->
- <skip />
- <!-- no translation found for notification_importance_default (4466466472622442175) -->
- <skip />
- <!-- no translation found for notification_importance_high (2135428926525093825) -->
- <skip />
- <!-- no translation found for notification_importance_max (5806278962376556491) -->
- <skip />
+ <string name="notification_importance_min" msgid="1938190340516905748">"Bonisa ngokuthulile ngaphansi kohlu lwesaziso"</string>
+ <string name="notification_importance_low" msgid="3657252049508213048">"Bonisa ngokuthulile lezi zaziso"</string>
+ <string name="notification_importance_default" msgid="4466466472622442175">"Vumela lezi zaziso ukwenza umsindo"</string>
+ <string name="notification_importance_high" msgid="2135428926525093825">"Beka kusikrini futhi uvumele umsindo"</string>
+ <string name="notification_importance_max" msgid="5806278962376556491">"Bonisa phezulu kohlu lwezaziso, beka phezu kwesikrini futhi uvumele umsindo"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Izilungiselelo eziningi"</string>
<string name="notification_done" msgid="5279426047273930175">"Kwenziwe"</string>
<string name="color_and_appearance" msgid="1254323855964993144">"Umbala nokubonakala"</string>
@@ -556,8 +544,7 @@
<item msgid="2139628951880142927">"Bonisa iphesentheji uma ishaja (okuzenzakalelayo)"</item>
<item msgid="3327323682209964956">"Ungabonisi lesi sithonjana"</item>
</string-array>
- <!-- no translation found for other (4060683095962566764) -->
- <skip />
+ <string name="other" msgid="4060683095962566764">"Okunye"</string>
<string name="accessibility_divider" msgid="5903423481953635044">"Isihlukanisi sokuhlukanisa isikrini"</string>
<string name="accessibility_action_divider_move_down" msgid="704893304141890042">"Iya phansi"</string>
<string name="accessibility_action_divider_move_up" msgid="4580103171609248006">"Iya phezulu"</string>
diff --git a/packages/SystemUI/res/values/colors_tv.xml b/packages/SystemUI/res/values/colors_tv.xml
index 6f4c983..af99aae 100644
--- a/packages/SystemUI/res/values/colors_tv.xml
+++ b/packages/SystemUI/res/values/colors_tv.xml
@@ -18,7 +18,5 @@
-->
<resources>
<color name="recents_tv_card_background_color">#FF37474F</color>
- <color name="recents_tv_card_title_text_color">#FFEEEEEE</color>
- <color name="recents_tv_card_content_text_color">#99EEEEEE</color>
- <color name="recents_tv_card_source_text_color">#99EEEEEE</color>
+ <color name="recents_tv_card_title_text_color">#CCEEEEEE</color>
</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index fbe0207..12c3a5d 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -292,6 +292,9 @@
<!-- The amount to allow the stack to overscroll. -->
<dimen name="recents_stack_overscroll">24dp</dimen>
+ <!-- The size of the initial peek area at the top of the stack (below the status bar). -->
+ <dimen name="recents_initial_top_peek_size">8dp</dimen>
+
<!-- The size of the peek area at the top of the stack (below the status bar). -->
<dimen name="recents_layout_focused_top_peek_size">@dimen/recents_history_button_height</dimen>
@@ -326,9 +329,6 @@
<!-- The minimum amount of top overscroll to go to the quick settings. -->
<dimen name="min_top_overscroll_to_qs">36dp</dimen>
- <!-- The padding to the second card when the notifications collapse. -->
- <dimen name="notification_collapse_second_card_padding">8dp</dimen>
-
<!-- The height of the speed bump view. -->
<dimen name="speed_bump_height">16dp</dimen>
diff --git a/packages/SystemUI/res/values/dimens_tv.xml b/packages/SystemUI/res/values/dimens_tv.xml
index bf32cc7..b589110 100644
--- a/packages/SystemUI/res/values/dimens_tv.xml
+++ b/packages/SystemUI/res/values/dimens_tv.xml
@@ -18,15 +18,21 @@
-->
<resources>
<!-- Dimens for recents card in the recents view on tv -->
- <dimen name="recents_tv_card_width">150dip</dimen>
- <dimen name="recents_tv_card_height">85dip</dimen>
- <dimen name="recents_tv_card_extra_badge_size">16dip</dimen>
+ <dimen name="recents_tv_card_width">268dip</dimen>
+ <dimen name="recents_tv_card_height">151dip</dimen>
+ <dimen name="recents_tv_card_extra_badge_size">20dip</dimen>
+ <dimen name="recents_tv_banner_width">114dip</dimen>
+ <dimen name="recents_tv_banner_height">64dip</dimen>
+ <dimen name="recents_tv_banner_margin_top">16dip</dimen>
+ <dimen name="recents_tv_icon_padding_bottom">8dip</dimen>
+ <dimen name="recents_tv_icon_padding_end">12dip</dimen>
+ <dimen name="recents_tv_text_padding_bottom">12dip</dimen>
<!-- Padding for grid view in recents view on tv -->
<dimen name="recents_tv_grid_row_padding">56dip</dimen>
<dimen name="recents_tv_gird_row_top_padding">57dip</dimen>
- <dimen name="recents_tv_grid_max_row_height">200dip</dimen>
- <dimen name="recents_tv_gird_card_spacing">8dip</dimen>
+ <dimen name="recents_tv_grid_max_row_height">268dip</dimen>
+ <dimen name="recents_tv_gird_card_spacing">20dip</dimen>
<!-- Values for focus animation -->
<dimen name="recents_tv_unselected_item_z">6dp</dimen>
@@ -34,4 +40,7 @@
<!-- Extra space around the PIP and its outline in PIP onboarding activity -->
<dimen name="tv_pip_bounds_space">3dp</dimen>
+
+ <!-- Values for text on recents cards on tv -->
+ <dimen name="recents_tv_title_text_size">12sp</dimen>
</resources>
diff --git a/packages/SystemUI/res/values/strings_tv.xml b/packages/SystemUI/res/values/strings_tv.xml
index 4f382ea..59cfb1e 100644
--- a/packages/SystemUI/res/values/strings_tv.xml
+++ b/packages/SystemUI/res/values/strings_tv.xml
@@ -31,11 +31,13 @@
<string name="pip_cancel" translatable="false">Cancel</string>
<!-- Overlay text on PIP -->
<string name="pip_hold_home" translatable="false">Hold HOME to control PIP</string>
-
<!-- Picture-in-Picture onboarding screen -->
<eat-comment />
<!-- Description for onboarding screen. -->
<string name="pip_onboarding_description" translatable="false">Press and hold the HOME\nbutton to close or control it</string>
<!-- Button to close onboarding screen. -->
<string name="pip_onboarding_button" translatable="false">Got it</string>
+ <!-- Font for Recents -->
+ <!-- DO NOT TRANSLATE -->
+ <string name="font_roboto_regular" translatable="false">sans-serif</string>
</resources>
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index a51b931..11df681 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -214,7 +214,7 @@
<style name="QSBorderlessButton">
<item name="android:padding">12dp</item>
- <item name="android:background">@drawable/btn_borderless_rect</item>
+ <item name="android:background">@drawable/qs_btn_borderless_rect</item>
<item name="android:gravity">center</item>
</style>
diff --git a/packages/SystemUI/res/values/styles_tv.xml b/packages/SystemUI/res/values/styles_tv.xml
index 3f0caab..263e1a4 100644
--- a/packages/SystemUI/res/values/styles_tv.xml
+++ b/packages/SystemUI/res/values/styles_tv.xml
@@ -22,4 +22,11 @@
<item name="android:windowBackground">@android:color/transparent</item>
<item name="android:backgroundDimEnabled">false</item>
</style>
+
+ <style name="RecentsTvTheme.Wallpaper" parent="@android:style/Theme.Material.NoActionBar.Overscan">
+ <item name="android:windowBackground">@android:color/transparent</item>
+ <item name="android:backgroundDimEnabled">false</item>
+ <item name="android:colorBackgroundCacheHint">@null</item>
+ <item name="android:windowIsTranslucent">true</item>
+ </style>
</resources>
diff --git a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
index 33f3c30..f6dcc11 100644
--- a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
@@ -144,7 +144,9 @@
protected Animator getViewTranslationAnimator(View v, float target,
AnimatorUpdateListener listener) {
ObjectAnimator anim = createTranslationAnimation(v, target);
- anim.addUpdateListener(listener);
+ if (listener != null) {
+ anim.addUpdateListener(listener);
+ }
return anim;
}
@@ -370,6 +372,9 @@
};
Animator anim = getViewTranslationAnimator(animView, newPos, updateListener);
+ if (anim == null) {
+ return;
+ }
if (useAccelerateInterpolator) {
anim.setInterpolator(Interpolators.FAST_OUT_LINEAR_IN);
} else {
@@ -411,6 +416,9 @@
};
Animator anim = getViewTranslationAnimator(animView, targetLeft, updateListener);
+ if (anim == null) {
+ return;
+ }
int duration = SNAP_ANIM_LEN;
anim.setDuration(duration);
anim.addListener(new AnimatorListenerAdapter() {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java b/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
index 2c5cb89..8ccf60d 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
@@ -77,7 +77,9 @@
@Override
public int getOffsetTop(TileRecord tile) {
- return ((ViewGroup) tile.tileView.getParent()).getTop() + getTop();
+ final ViewGroup parent = (ViewGroup) tile.tileView.getParent();
+ if (parent == null) return 0;
+ return parent.getTop() + getTop();
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
index 225c10f..5e02428 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
@@ -87,6 +87,7 @@
mToolbar.setOnMenuItemClickListener(this);
mToolbar.getMenu().add(Menu.NONE, MENU_RESET, 0,
mContext.getString(com.android.internal.R.string.reset));
+ mToolbar.setTitle(R.string.qs_edit);
mRecyclerView = (RecyclerView) findViewById(android.R.id.list);
mTileAdapter = new TileAdapter(getContext());
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
index aba9251..d9b3b3f 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
@@ -25,7 +25,6 @@
import android.support.v7.widget.RecyclerView.ViewHolder;
import android.support.v7.widget.helper.ItemTouchHelper;
import android.view.LayoutInflater;
-import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
@@ -277,9 +276,6 @@
return false;
}
}
- if (target.getItemViewType() == TYPE_EDIT && from < mDividerIndex) {
- to++;
- }
move(from, to, mTiles);
mDividerIndex = mTiles.indexOf(null);
notifyItemMoved(from, to);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java b/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java
index aa85f78..d95d3ef 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java
@@ -28,8 +28,6 @@
import android.os.Handler;
import android.os.Looper;
import android.service.quicksettings.TileService;
-import com.android.systemui.Prefs;
-import com.android.systemui.Prefs.Key;
import com.android.systemui.R;
import com.android.systemui.qs.QSTile;
import com.android.systemui.qs.QSTile.DrawableIcon;
@@ -57,10 +55,8 @@
}
private void addSystemTiles(QSTileHost host) {
- boolean hasColorMod = Prefs.getBoolean(host.getContext(), Key.QS_NIGHT_ADDED, false)
- && TunerService.isTunerEnabled(host.getContext());
String possible = mContext.getString(R.string.quick_settings_tiles_default)
- + ",hotspot,inversion,saver,work,cast" + (hasColorMod ? ",night" : "");
+ + ",hotspot,inversion,saver,work,cast,night";
String[] possibleTiles = possible.split(",");
final Handler qsHandler = new Handler(host.getLooper());
final Handler mainHandler = new Handler(Looper.getMainLooper());
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BatteryTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BatteryTile.java
index 39d1447..2e87525 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BatteryTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BatteryTile.java
@@ -172,6 +172,7 @@
}
private void postBindView() {
+ if (mCurrentView == null) return;
mCurrentView.post(new Runnable() {
@Override
public void run() {
@@ -181,6 +182,9 @@
}
private void bindView() {
+ if (mCurrentView == null) {
+ return;
+ }
mDrawable.onBatteryLevelChanged(100, false, false);
mDrawable.onPowerSaveChanged(true);
mDrawable.disableShowPercent();
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index c41098f..a2934d7 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
@@ -43,6 +43,7 @@
import com.android.systemui.recents.events.EventBus;
import com.android.systemui.recents.events.activity.AppWidgetProviderChangedEvent;
import com.android.systemui.recents.events.activity.CancelEnterRecentsWindowAnimationEvent;
+import com.android.systemui.recents.events.activity.ConfigurationChangedEvent;
import com.android.systemui.recents.events.activity.DebugFlagsChangedEvent;
import com.android.systemui.recents.events.activity.DismissRecentsToHomeAnimationStarted;
import com.android.systemui.recents.events.activity.EnterRecentsWindowAnimationCompletedEvent;
@@ -107,7 +108,7 @@
private RecentsAppWidgetHostView mSearchWidgetHostView;
// Runnables to finish the Recents activity
- private FinishRecentsRunnable mFinishLaunchHomeRunnable;
+ private Intent mHomeIntent;
// The trigger to automatically launch the current task
private int mFocusTimerDuration;
@@ -119,7 +120,7 @@
* last activity launch state. Generally we always launch home when we exit Recents rather than
* just finishing the activity since we don't know what is behind Recents in the task stack.
*/
- class FinishRecentsRunnable implements Runnable {
+ class LaunchHomeRunnable implements Runnable {
Intent mLaunchIntent;
ActivityOptions mOpts;
@@ -127,7 +128,7 @@
/**
* Creates a finish runnable that starts the specified intent.
*/
- public FinishRecentsRunnable(Intent launchIntent, ActivityOptions opts) {
+ public LaunchHomeRunnable(Intent launchIntent, ActivityOptions opts) {
mLaunchIntent = launchIntent;
mOpts = opts;
}
@@ -215,7 +216,7 @@
MetricsLogger.count(this, "overview_trigger_nav_btn", 1);
}
// Keep track of whether we launched from an app or from home
- if (launchState.launchedFromAppWithThumbnail) {
+ if (launchState.launchedFromApp) {
MetricsLogger.count(this, "overview_source_app", 1);
// If from an app, track the stack index of the app in the stack (for affiliated tasks)
MetricsLogger.histogram(this, "overview_source_app_index", launchTaskIndexInStack);
@@ -294,12 +295,8 @@
void dismissRecentsToHome(boolean animateTaskViews, ActivityOptions overrideAnimation) {
DismissRecentsToHomeAnimationStarted dismissEvent =
new DismissRecentsToHomeAnimationStarted(animateTaskViews);
- if (overrideAnimation != null) {
- dismissEvent.addPostAnimationCallback(new FinishRecentsRunnable(
- mFinishLaunchHomeRunnable.mLaunchIntent, overrideAnimation));
- } else {
- dismissEvent.addPostAnimationCallback(mFinishLaunchHomeRunnable);
- }
+ dismissEvent.addPostAnimationCallback(new LaunchHomeRunnable(mHomeIntent,
+ overrideAnimation));
dismissEvent.addPostAnimationCallback(new Runnable() {
@Override
public void run() {
@@ -365,11 +362,10 @@
});
// Create the home intent runnable
- Intent homeIntent = new Intent(Intent.ACTION_MAIN, null);
- homeIntent.addCategory(Intent.CATEGORY_HOME);
- homeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
+ mHomeIntent = new Intent(Intent.ACTION_MAIN, null);
+ mHomeIntent.addCategory(Intent.CATEGORY_HOME);
+ mHomeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
- mFinishLaunchHomeRunnable = new FinishRecentsRunnable(homeIntent, null);
// Bind the search app widget when we first start up
if (RecentsDebugFlags.Static.EnableSearchBar) {
@@ -404,7 +400,7 @@
RecentsConfiguration config = Recents.getConfiguration();
RecentsActivityLaunchState launchState = config.getLaunchState();
boolean wasLaunchedByAm = !launchState.launchedFromHome &&
- !launchState.launchedFromAppWithThumbnail;
+ !launchState.launchedFromApp;
if (launchState.launchedHasConfigurationChanged || wasLaunchedByAm) {
EventBus.getDefault().send(new EnterRecentsWindowAnimationCompletedEvent());
}
@@ -528,6 +524,7 @@
@Override
public void onMultiWindowChanged(boolean inMultiWindow) {
super.onMultiWindowChanged(inMultiWindow);
+ EventBus.getDefault().send(new ConfigurationChangedEvent());
RecentsTaskLoader loader = Recents.getTaskLoader();
RecentsTaskLoadPlan.Options launchOpts = new RecentsTaskLoadPlan.Options();
launchOpts.loadIcons = false;
@@ -636,7 +633,7 @@
// Focus the next task
EventBus.getDefault().send(new FocusNextTaskViewEvent(timerIndicatorDuration));
- MetricsLogger.action(this, MetricsEvent.OVERVIEW_PAGE);
+ MetricsLogger.action(this, MetricsEvent.ACTION_OVERVIEW_PAGE);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivityLaunchState.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivityLaunchState.java
index aa1437b..ec4820a 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivityLaunchState.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivityLaunchState.java
@@ -28,7 +28,8 @@
public class RecentsActivityLaunchState {
public boolean launchedWithAltTab;
- public boolean launchedFromAppWithThumbnail;
+ public boolean launchedFromApp;
+ public boolean launchedFromAppDocked;
public boolean launchedFromHome;
public boolean launchedFromSearchHome;
public boolean launchedReuseTaskStackViews;
@@ -42,7 +43,8 @@
public void reset() {
launchedFromHome = false;
launchedFromSearchHome = false;
- launchedFromAppWithThumbnail = false;
+ launchedFromApp = false;
+ launchedFromAppDocked = false;
launchedToTaskId = -1;
launchedWithAltTab = false;
launchedHasConfigurationChanged = false;
@@ -67,7 +69,7 @@
public int getInitialFocusTaskIndex(int numTasks) {
RecentsDebugFlags debugFlags = Recents.getDebugFlags();
RecentsActivityLaunchState launchState = Recents.getConfiguration().getLaunchState();
- if (launchedFromAppWithThumbnail) {
+ if (launchedFromApp) {
if (!launchState.launchedWithAltTab && debugFlags.isFastToggleRecentsEnabled()) {
// If fast toggling, focus the front most task so that the next tap will focus the
// N-1 task
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
index 9e43bb4..eec0411 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
@@ -69,7 +69,6 @@
public final int smallestWidth;
/** Misc **/
- public boolean useHardwareLayers;
public boolean fakeShadows;
public int svelteLevel;
public int searchBarSpaceHeightPx;
@@ -80,7 +79,6 @@
SystemServicesProxy ssp = Recents.getSystemServices();
Context appContext = context.getApplicationContext();
Resources res = appContext.getResources();
- useHardwareLayers = res.getBoolean(R.bool.config_recents_use_hardware_layers);
fakeShadows = res.getBoolean(R.bool.config_recents_fake_shadows);
svelteLevel = res.getInteger(R.integer.recents_svelte_level);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsDebugFlags.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsDebugFlags.java
index cd64323..6feda81 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsDebugFlags.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsDebugFlags.java
@@ -39,8 +39,8 @@
public static final boolean EnableAffiliatedTaskGroups = true;
// Enables the history
public static final boolean EnableHistory = false;
- // Overrides the Tuner flags and enables the fast toggle and timeout
- public static final boolean EnableFastToggleTimeoutOverride = true;
+ // Overrides the Tuner flags and enables the timeout
+ private static final boolean EnableFastToggleTimeout = false;
// Enables us to create mock recents tasks
public static final boolean EnableMockTasks = false;
@@ -54,9 +54,9 @@
public static final int MockTaskGroupsTaskCount = 12;
}
- private static final String KEY_DISABLE_FAST_TOGGLE = "overview_disable_fast_toggle_via_button";
+ private static final String KEY_ENABLE_PAGING = "overview_enable_paging";
- private boolean mDisableFastToggleRecents;
+ private boolean mEnablePaging;
/**
* We read the prefs once when we start the activity, then update them as the tuner changes
@@ -65,31 +65,32 @@
public RecentsDebugFlags(Context context) {
// Register all our flags, this will also call onTuningChanged() for each key, which will
// initialize the current state of each flag
- TunerService.get(context).addTunable(this, KEY_DISABLE_FAST_TOGGLE);
+ TunerService.get(context).addTunable(this, KEY_ENABLE_PAGING);
}
/**
* @return whether we are enabling fast toggling.
*/
public boolean isFastToggleRecentsEnabled() {
- // These checks EnableFastToggleTimeoutOverride
SystemServicesProxy ssp = Recents.getSystemServices();
- if (mDisableFastToggleRecents || ssp.hasFreeformWorkspaceSupport() || ssp.hasDockedTask()
- || ssp.isTouchExplorationEnabled()) {
+ if (ssp.hasFreeformWorkspaceSupport() || ssp.isTouchExplorationEnabled()) {
return false;
}
- if (Static.EnableFastToggleTimeoutOverride) {
- return true;
- }
- return true;
+ return Static.EnableFastToggleTimeout;
+ }
+
+ /**
+ * @return whether we are enabling paging.
+ */
+ public boolean isPagingEnabled() {
+ return mEnablePaging;
}
@Override
public void onTuningChanged(String key, String newValue) {
switch (key) {
- case KEY_DISABLE_FAST_TOGGLE:
- mDisableFastToggleRecents = (newValue != null) &&
- (Integer.parseInt(newValue) != 0);
+ case KEY_ENABLE_PAGING:
+ mEnablePaging = (newValue != null) && (Integer.parseInt(newValue) != 0);
break;
}
EventBus.getDefault().send(new DebugFlagsChangedEvent());
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
index 28b2fae..1458d7b 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
@@ -16,6 +16,8 @@
package com.android.systemui.recents;
+import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
+
import android.app.ActivityManager;
import android.app.ActivityOptions;
import android.app.ITaskStackListener;
@@ -64,8 +66,10 @@
import com.android.systemui.recents.model.Task;
import com.android.systemui.recents.model.TaskGrouping;
import com.android.systemui.recents.model.TaskStack;
+import com.android.systemui.recents.tv.views.TaskStackHorizontalGridView;
import com.android.systemui.recents.views.TaskStackLayoutAlgorithm;
import com.android.systemui.recents.views.TaskStackView;
+import com.android.systemui.recents.views.TaskStackViewScroller;
import com.android.systemui.recents.views.TaskViewHeader;
import com.android.systemui.recents.views.TaskViewTransform;
import com.android.systemui.statusbar.BaseStatusBar;
@@ -74,8 +78,6 @@
import java.util.ArrayList;
-import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
-
/**
* An implementation of the Recents component for the current user. For secondary users, this can
* be called remotely from the system user.
@@ -98,6 +100,7 @@
//Used to store tv or non-tv activty for use in creating intents.
private final String mRecentsIntentActivityName;
+
/**
* An implementation of ITaskStackListener, that allows us to listen for changes to the system
* task stacks and update recents accordingly.
@@ -276,28 +279,24 @@
mTriggeredFromAltTab = triggeredFromAltTab;
mDraggingInRecents = draggingInRecents;
mLaunchedWhileDocking = launchedWhileDockingTask;
- if (mFastAltTabTrigger.hasTriggered()) {
- // We are calling this from the doze trigger, so just fall through to show Recents
- mFastAltTabTrigger.resetTrigger();
+ if (mFastAltTabTrigger.isAsleep()) {
+ // Fast alt-tab duration has elapsed, fall through to showing Recents and reset
+ mFastAltTabTrigger.stopDozing();
} else if (mFastAltTabTrigger.isDozing()) {
- // We are dozing but haven't yet triggered, ignore this if this is not another alt-tab,
- // otherwise, this is an additional tab (alt-tab*), which means that we should trigger
- // immediately (fall through and disable the pending trigger)
- // TODO: This is tricky, we need to handle the tab key, but Recents has not yet started
- // so we may actually additional signal to handle multiple quick tab cases. The
- // severity of this is inversely proportional to the FAST_ALT_TAB_DELAY_MS
- // duration though
+ // Fast alt-tab duration has not elapsed. If this is triggered by a different
+ // showRecents() call, then ignore that call for now.
+ // TODO: We can not handle quick tabs that happen between the initial showRecents() call
+ // that started the activity and the activity starting up. The severity of this
+ // is inversely proportional to the FAST_ALT_TAB_DELAY_MS duration though.
if (!triggeredFromAltTab) {
return;
}
mFastAltTabTrigger.stopDozing();
- } else {
- // Otherwise, the doze trigger is not running, and if this is an alt tab, we should
- // start the trigger and then wait for the hide (or for it to elapse)
- if (triggeredFromAltTab) {
- mFastAltTabTrigger.startDozing();
- return;
- }
+ } else if (triggeredFromAltTab) {
+ // The fast alt-tab detector is not yet running, so start the trigger and wait for the
+ // hideRecents() call, or for the fast alt-tab duration to elapse
+ mFastAltTabTrigger.startDozing();
+ return;
}
try {
@@ -321,7 +320,6 @@
// Cancel the fast alt-tab trigger
mFastAltTabTrigger.stopDozing();
- mFastAltTabTrigger.resetTrigger();
return;
}
@@ -348,12 +346,14 @@
long elapsedTime = SystemClock.elapsedRealtime() - mLastToggleTime;
if (topTask != null && ssp.isRecentsTopMost(topTask, isTopTaskHome)) {
+ RecentsDebugFlags debugFlags = Recents.getDebugFlags();
RecentsConfiguration config = Recents.getConfiguration();
RecentsActivityLaunchState launchState = config.getLaunchState();
if (!launchState.launchedWithAltTab) {
// If the user taps quickly
- if (ViewConfiguration.getDoubleTapMinTime() < elapsedTime &&
- elapsedTime < ViewConfiguration.getDoubleTapTimeout()) {
+ if (!debugFlags.isPagingEnabled() ||
+ (ViewConfiguration.getDoubleTapMinTime() < elapsedTime &&
+ elapsedTime < ViewConfiguration.getDoubleTapTimeout())) {
// Launch the next focused task
EventBus.getDefault().post(new LaunchNextTaskRequestEvent());
} else {
@@ -568,11 +568,14 @@
// Make sure we inform DividerView before we actually start the activity so we can change
// the resize mode already.
- EventBus.getDefault().send(new DockingTopTaskEvent(dragMode));
- ssp.moveTaskToDockedStack(topTaskId, stackCreateMode, initialBounds);
- showRecents(false /* triggeredFromAltTab */,
- dragMode == NavigationBarGestureHelper.DRAG_MODE_RECENTS, false /* animate */,
- true /* reloadTasks*/);
+ if (ssp.moveTaskToDockedStack(topTaskId, stackCreateMode, initialBounds)) {
+ EventBus.getDefault().send(new DockingTopTaskEvent(dragMode));
+ showRecents(
+ false /* triggeredFromAltTab */,
+ dragMode == NavigationBarGestureHelper.DRAG_MODE_RECENTS,
+ false /* animate */,
+ true /* launchedWhileDockingTask*/);
+ }
}
/**
@@ -704,8 +707,7 @@
// Update the destination rect
mDummyStackView.updateLayoutForStack(stack);
final Task toTask = new Task();
- final TaskViewTransform toTransform = getThumbnailTransitionTransform(stack, stackView,
- toTask);
+ final TaskViewTransform toTransform = getThumbnailTransitionTransform(stackView, toTask);
ForegroundThread.getHandler().postAtFrontOfQueue(new Runnable() {
@Override
public void run() {
@@ -751,17 +753,20 @@
* Creates the activity options for an app->recents transition.
*/
private ActivityOptions getThumbnailTransitionActivityOptions(
- ActivityManager.RunningTaskInfo topTask, TaskStack stack, TaskStackView stackView) {
+ ActivityManager.RunningTaskInfo topTask, TaskStackView stackView) {
if (topTask.stackId == FREEFORM_WORKSPACE_STACK_ID) {
ArrayList<AppTransitionAnimationSpec> specs = new ArrayList<>();
- stackView.getScroller().setStackScrollToInitialState();
- ArrayList<Task> tasks = stack.getStackTasks();
+ ArrayList<Task> tasks = stackView.getStack().getStackTasks();
+ TaskStackLayoutAlgorithm stackLayout = stackView.getStackAlgorithm();
+ TaskStackViewScroller stackScroller = stackView.getScroller();
+
+ stackView.updateToInitialState();
+
for (int i = tasks.size() - 1; i >= 0; i--) {
Task task = tasks.get(i);
if (task.isFreeformTask()) {
- mTmpTransform = stackView.getStackAlgorithm()
- .getStackTransformScreenCoordinates(task,
- stackView.getScroller().getStackScroll(), mTmpTransform, null);
+ mTmpTransform = stackLayout.getStackTransformScreenCoordinates(task,
+ stackScroller.getStackScroll(), mTmpTransform, null);
Rect toTaskRect = new Rect();
mTmpTransform.rect.round(toTaskRect);
Bitmap thumbnail = getThumbnailBitmap(topTask, task, mTmpTransform);
@@ -775,8 +780,7 @@
} else {
// Update the destination rect
Task toTask = new Task();
- TaskViewTransform toTransform = getThumbnailTransitionTransform(stack, stackView,
- toTask);
+ TaskViewTransform toTransform = getThumbnailTransitionTransform(stackView, toTask);
RectF toTaskRect = toTransform.rect;
Bitmap thumbnail = getThumbnailBitmap(topTask, toTask, toTransform);
if (thumbnail != null) {
@@ -808,9 +812,10 @@
/**
* Returns the transition rect for the given task id.
*/
- private TaskViewTransform getThumbnailTransitionTransform(TaskStack stack,
- TaskStackView stackView, Task runningTaskOut) {
+ private TaskViewTransform getThumbnailTransitionTransform(TaskStackView stackView,
+ Task runningTaskOut) {
// Find the running task in the TaskStack
+ TaskStack stack = stackView.getStack();
Task launchTask = stack.getLaunchTarget();
if (launchTask != null) {
runningTaskOut.copyFrom(launchTask);
@@ -821,7 +826,7 @@
}
// Get the transform for the running task
- stackView.getScroller().setStackScrollToInitialState();
+ stackView.updateToInitialState();
mTmpTransform = stackView.getStackAlgorithm().getStackTransformScreenCoordinates(launchTask,
stackView.getScroller().getStackScroll(), mTmpTransform, null);
return mTmpTransform;
@@ -849,6 +854,7 @@
c.scale(toTransform.scale, toTransform.scale);
mHeaderBar.rebindToTask(toTask, false /* touchExplorationEnabled */,
disabledInSafeMode);
+ mHeaderBar.setDimAlpha(toTransform.dimAlpha);
mHeaderBar.draw(c);
c.setBitmap(null);
}
@@ -897,8 +903,7 @@
if (useThumbnailTransition) {
// Try starting with a thumbnail transition
- ActivityOptions opts = getThumbnailTransitionActivityOptions(topTask, stack,
- mDummyStackView);
+ ActivityOptions opts = getThumbnailTransitionActivityOptions(topTask, mDummyStackView);
if (opts != null) {
startRecentsActivity(topTask, opts, false /* fromHome */,
false /* fromSearchHome */, true /* fromThumbnail */, stackVr);
@@ -945,14 +950,15 @@
* Starts the recents activity.
*/
private void startRecentsActivity(ActivityManager.RunningTaskInfo topTask,
- ActivityOptions opts, boolean fromHome, boolean fromSearchHome, boolean fromThumbnail,
- TaskStackLayoutAlgorithm.VisibilityReport vr) {
+ ActivityOptions opts, boolean fromHome, boolean fromSearchHome,
+ boolean fromThumbnail, TaskStackLayoutAlgorithm.VisibilityReport vr) {
// Update the configuration based on the launch options
RecentsConfiguration config = Recents.getConfiguration();
RecentsActivityLaunchState launchState = config.getLaunchState();
launchState.launchedFromHome = fromSearchHome || fromHome;
launchState.launchedFromSearchHome = fromSearchHome;
- launchState.launchedFromAppWithThumbnail = fromThumbnail;
+ launchState.launchedFromApp = fromThumbnail || mLaunchedWhileDocking;
+ launchState.launchedFromAppDocked = mLaunchedWhileDocking;
launchState.launchedToTaskId = (topTask != null) ? topTask.id : -1;
launchState.launchedWithAltTab = mTriggeredFromAltTab;
launchState.launchedReuseTaskStackViews = mCanReuseTaskStackViews;
diff --git a/core/java/android/hardware/camera2/utils/LongParcelable.aidl b/packages/SystemUI/src/com/android/systemui/recents/events/activity/ConfigurationChangedEvent.java
similarity index 62%
rename from core/java/android/hardware/camera2/utils/LongParcelable.aidl
rename to packages/SystemUI/src/com/android/systemui/recents/events/activity/ConfigurationChangedEvent.java
index 98ad1b2..0ad4681 100644
--- a/core/java/android/hardware/camera2/utils/LongParcelable.aidl
+++ b/packages/SystemUI/src/com/android/systemui/recents/events/activity/ConfigurationChangedEvent.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2014 The Android Open Source Project
+ * 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.
@@ -14,7 +14,13 @@
* limitations under the License.
*/
-package android.hardware.camera2.utils;
+package com.android.systemui.recents.events.activity;
-/** @hide */
-parcelable LongParcelable;
+import com.android.systemui.recents.events.EventBus;
+
+/**
+ * This is sent when the Recents activity configuration has changed.
+ */
+public class ConfigurationChangedEvent extends EventBus.AnimatedEvent {
+ // Simple event
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/LaunchTvTaskEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/activity/LaunchTvTaskEvent.java
new file mode 100644
index 0000000..04ca68f
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recents/events/activity/LaunchTvTaskEvent.java
@@ -0,0 +1,39 @@
+/*
+ * 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.
+ */
+package com.android.systemui.recents.events.activity;
+
+
+import android.graphics.Rect;
+import com.android.systemui.recents.events.EventBus;
+import com.android.systemui.recents.model.Task;
+import com.android.systemui.recents.tv.views.TaskCardView;
+
+public class LaunchTvTaskEvent extends EventBus.Event {
+
+ public final TaskCardView taskView;
+ public final Task task;
+ public final Rect targetTaskBounds;
+ public final int targetTaskStack;
+
+ public LaunchTvTaskEvent(TaskCardView taskView, Task task, Rect targetTaskBounds,
+ int targetTaskStack) {
+ this.taskView = taskView;
+ this.task = task;
+ this.targetTaskBounds = targetTaskBounds;
+ this.targetTaskStack = targetTaskStack;
+ }
+
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/LaunchTvTaskStartedEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/activity/LaunchTvTaskStartedEvent.java
new file mode 100644
index 0000000..75d3efa
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recents/events/activity/LaunchTvTaskStartedEvent.java
@@ -0,0 +1,34 @@
+/*
+ * 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.
+ */
+
+package com.android.systemui.recents.events.activity;
+
+import com.android.systemui.recents.events.EventBus;
+import com.android.systemui.recents.tv.views.TaskCardView;
+
+/**
+ * This event is sent following {@link LaunchTvTaskEvent} after the call to the system is made to
+ * start the task, only used on TV.
+ */
+public class LaunchTvTaskStartedEvent extends EventBus.AnimatedEvent {
+
+ public final TaskCardView taskView;
+
+ public LaunchTvTaskStartedEvent(TaskCardView taskView) {
+ this.taskView = taskView;
+ }
+
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/history/RecentsHistoryAdapter.java b/packages/SystemUI/src/com/android/systemui/recents/history/RecentsHistoryAdapter.java
index d7b9b9e..5eeda72 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/history/RecentsHistoryAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/history/RecentsHistoryAdapter.java
@@ -161,7 +161,7 @@
ssp.startActivityFromRecents(v.getContext(), task.key.id, task.title,
ActivityOptions.makeBasic());
- MetricsLogger.action(v.getContext(), MetricsEvent.OVERVIEW_SELECT,
+ MetricsLogger.action(v.getContext(), MetricsEvent.ACTION_OVERVIEW_SELECT,
task.key.getComponent().toString());
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/DozeTrigger.java b/packages/SystemUI/src/com/android/systemui/recents/misc/DozeTrigger.java
index 95aa10f..574ea03 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/DozeTrigger.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/misc/DozeTrigger.java
@@ -30,7 +30,7 @@
@ViewDebug.ExportedProperty(category="recents")
boolean mIsDozing;
@ViewDebug.ExportedProperty(category="recents")
- boolean mHasTriggered;
+ boolean mIsAsleep;
@ViewDebug.ExportedProperty(category="recents")
int mDozeDurationMilliseconds;
Runnable mOnSleepRunnable;
@@ -40,7 +40,7 @@
@Override
public void run() {
mIsDozing = false;
- mHasTriggered = true;
+ mIsAsleep = true;
mOnSleepRunnable.run();
}
};
@@ -56,7 +56,7 @@
*/
public void startDozing() {
forcePoke();
- mHasTriggered = false;
+ mIsAsleep = false;
}
/**
@@ -65,6 +65,7 @@
public void stopDozing() {
mHandler.removeCallbacks(mDozeRunnable);
mIsDozing = false;
+ mIsAsleep = false;
}
/**
@@ -99,12 +100,7 @@
}
/** Returns whether the trigger has fired at least once. */
- public boolean hasTriggered() {
- return mHasTriggered;
- }
-
- /** Resets the doze trigger state. */
- public void resetTrigger() {
- mHasTriggered = false;
+ public boolean isAsleep() {
+ return mIsAsleep;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
index 4b29c29..532e796 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
@@ -338,15 +338,18 @@
}
/** Docks an already resumed task to the side of the screen. */
- public void moveTaskToDockedStack(int taskId, int createMode, Rect initialBounds) {
- if (mIam == null) return;
+ public boolean moveTaskToDockedStack(int taskId, int createMode, Rect initialBounds) {
+ if (mIam == null) {
+ return false;
+ }
try {
- mIam.moveTaskToDockedStack(taskId, createMode, true /* onTop */, false /* animate */,
- initialBounds);
+ return mIam.moveTaskToDockedStack(
+ taskId, createMode, true /* onTop */, false /* animate */, initialBounds);
} catch (RemoteException e) {
e.printStackTrace();
}
+ return false;
}
/** Returns the focused stack id. */
@@ -692,6 +695,37 @@
}
/**
+ * Returns a banner used on TV for the specified Activity.
+ */
+ public Drawable getActivityBanner(ActivityInfo info) {
+ if (mPm == null) return null;
+
+ // If we are mocking, then return a mock banner
+ if (RecentsDebugFlags.Static.EnableMockTasks) {
+ return new ColorDrawable(0xFF666666);
+ }
+
+ Drawable banner = info.loadBanner(mPm);
+ return banner;
+ }
+
+ /**
+ * Returns a logo used on TV for the specified Activity.
+ */
+ public Drawable getActivityLogo(ActivityInfo info) {
+ if (mPm == null) return null;
+
+ // If we are mocking, then return a mock logo
+ if (RecentsDebugFlags.Static.EnableMockTasks) {
+ return new ColorDrawable(0xFF666666);
+ }
+
+ Drawable logo = info.loadLogo(mPm);
+ return logo;
+ }
+
+
+ /**
* Returns the given label for a user, badging if necessary.
*/
private String getBadgedLabel(String label, int userId) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/tv/RecentsTvActivity.java b/packages/SystemUI/src/com/android/systemui/recents/tv/RecentsTvActivity.java
index 0c48cf7..02c8d96 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/tv/RecentsTvActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/tv/RecentsTvActivity.java
@@ -40,7 +40,6 @@
import com.android.systemui.recents.events.activity.EnterRecentsWindowLastAnimationFrameEvent;
import com.android.systemui.recents.events.activity.HideRecentsEvent;
import com.android.systemui.recents.events.activity.LaunchTaskFailedEvent;
-import com.android.systemui.recents.events.activity.TaskStackUpdatedEvent;
import com.android.systemui.recents.events.activity.ToggleRecentsEvent;
import com.android.systemui.recents.events.component.RecentsVisibilityChangedEvent;
import com.android.systemui.recents.events.ui.AllTaskViewsDismissedEvent;
@@ -60,6 +59,8 @@
import com.android.systemui.tv.pip.PipManager;
import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
/**
* The main TV recents activity started by the RecentsImpl.
@@ -157,11 +158,13 @@
mRecentsView.setTaskStack(stack);
+ List stackTasks = stack.getStackTasks();
+ Collections.reverse(stackTasks);
if (mTaskStackViewAdapter == null) {
- mTaskStackViewAdapter = new TaskStackHorizontalViewAdapter(stack.getStackTasks());
+ mTaskStackViewAdapter = new TaskStackHorizontalViewAdapter(stackTasks);
mRecentsView.setTaskStackViewAdapter(mTaskStackViewAdapter);
} else {
- mTaskStackViewAdapter.setNewStackTasks(stack.getStackTasks());
+ mTaskStackViewAdapter.setNewStackTasks(stackTasks);
}
if (launchState.launchedToTaskId != -1) {
@@ -284,7 +287,7 @@
RecentsConfiguration config = Recents.getConfiguration();
RecentsActivityLaunchState launchState = config.getLaunchState();
boolean wasLaunchedByAm = !launchState.launchedFromHome &&
- !launchState.launchedFromAppWithThumbnail;
+ !launchState.launchedFromApp;
if (launchState.launchedHasConfigurationChanged || wasLaunchedByAm) {
EventBus.getDefault().send(new EnterRecentsWindowAnimationCompletedEvent());
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/tv/views/RecentsTvTransitionHelper.java b/packages/SystemUI/src/com/android/systemui/recents/tv/views/RecentsTvTransitionHelper.java
new file mode 100644
index 0000000..ef8d48e
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recents/tv/views/RecentsTvTransitionHelper.java
@@ -0,0 +1,132 @@
+/*
+ * 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.
+ */
+package com.android.systemui.recents.tv.views;
+
+import android.annotation.Nullable;
+import android.app.ActivityManager;
+import android.app.ActivityOptions;
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.Rect;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.IRemoteCallback;
+import android.os.RemoteException;
+import android.util.Log;
+import android.view.WindowManagerGlobal;
+import com.android.internal.annotations.GuardedBy;
+import com.android.systemui.recents.Recents;
+import com.android.systemui.recents.events.EventBus;
+import com.android.systemui.recents.events.activity.*;
+import com.android.systemui.recents.misc.SystemServicesProxy;
+import com.android.systemui.recents.model.Task;
+import com.android.systemui.recents.model.TaskStack;
+
+
+public class RecentsTvTransitionHelper {
+ private static final String TAG = "RecentsTvTransitionHelper";
+
+ private Context mContext;
+ private Handler mHandler;
+
+ public RecentsTvTransitionHelper(Context context, Handler handler) {
+ mContext = context;
+ mHandler = handler;
+ }
+
+ public void launchTaskFromRecents(final TaskStack stack, @Nullable final Task task,
+ final TaskStackHorizontalGridView stackView, final TaskCardView taskView,
+ final Rect bounds, int destinationStack) {
+ final ActivityOptions opts = ActivityOptions.makeBasic();
+ if (bounds != null) {
+ opts.setLaunchBounds(bounds.isEmpty() ? null : bounds);
+ }
+
+ final ActivityOptions.OnAnimationStartedListener animStartedListener;
+ if (task.thumbnail != null && task.thumbnail.getWidth() > 0 &&
+ task.thumbnail.getHeight() > 0) {
+ animStartedListener = new ActivityOptions.OnAnimationStartedListener() {
+ @Override
+ public void onAnimationStarted() {
+ // If we are launching into another task, cancel the previous task's
+ // window transition
+ EventBus.getDefault().send(new CancelEnterRecentsWindowAnimationEvent(task));
+ EventBus.getDefault().send(new ExitRecentsWindowFirstAnimationFrameEvent());
+ }
+ };
+ } else {
+ // This is only the case if the task is not on screen (scrolled offscreen for example)
+ animStartedListener = new ActivityOptions.OnAnimationStartedListener() {
+ @Override
+ public void onAnimationStarted() {
+ EventBus.getDefault().send(new ExitRecentsWindowFirstAnimationFrameEvent());
+ }
+ };
+ }
+
+ if (taskView == null) {
+ // If there is no task view, then we do not need to worry about animating out occluding
+ // task views, and we can launch immediately
+ startTaskActivity(stack, task, taskView, opts, animStartedListener);
+ } else {
+ LaunchTvTaskStartedEvent launchStartedEvent = new LaunchTvTaskStartedEvent(taskView);
+ EventBus.getDefault().send(launchStartedEvent);
+ startTaskActivity(stack, task, taskView, opts, animStartedListener);
+ }
+ }
+
+ private void startTaskActivity(TaskStack stack, Task task, @Nullable TaskCardView taskView,
+ ActivityOptions opts,final ActivityOptions.OnAnimationStartedListener animStartedListener) {
+ SystemServicesProxy ssp = Recents.getSystemServices();
+ if (ssp.startActivityFromRecents(mContext, task.key.id, task.title, opts)) {
+ // Keep track of the index of the task launch
+ int taskIndexFromFront = 0;
+ int taskIndex = stack.indexOfStackTask(task);
+ if (taskIndex > -1) {
+ taskIndexFromFront = stack.getTaskCount() - taskIndex - 1;
+ }
+ EventBus.getDefault().send(new LaunchTaskSucceededEvent(taskIndexFromFront));
+ } else {
+ // Keep track of failed launches
+ EventBus.getDefault().send(new LaunchTaskFailedEvent());
+ }
+
+ IRemoteCallback.Stub callback = null;
+ if (animStartedListener != null) {
+ callback = new IRemoteCallback.Stub() {
+ @Override
+ public void sendResult(Bundle data) throws RemoteException {
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ if (animStartedListener != null) {
+ animStartedListener.onAnimationStarted();
+ }
+ }
+ });
+ }
+ };
+ }
+ try {
+ Rect taskRect = taskView.getGlobalRect();
+ WindowManagerGlobal.getWindowManagerService()
+ .overridePendingAppTransitionThumb(task.thumbnail, taskRect.left,
+ taskRect.top, callback, true);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed to override transition: " + e);
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/tv/views/RecentsTvView.java b/packages/SystemUI/src/com/android/systemui/recents/tv/views/RecentsTvView.java
index 8e768a2..bf6229c 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/tv/views/RecentsTvView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/tv/views/RecentsTvView.java
@@ -17,6 +17,7 @@
import android.content.Context;
import android.graphics.Rect;
+import android.os.Handler;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
@@ -31,7 +32,7 @@
import com.android.systemui.recents.events.EventBus;
import com.android.systemui.recents.events.activity.CancelEnterRecentsWindowAnimationEvent;
import com.android.systemui.recents.events.activity.DismissRecentsToHomeAnimationStarted;
-import com.android.systemui.recents.events.activity.TaskStackUpdatedEvent;
+import com.android.systemui.recents.events.activity.LaunchTvTaskEvent;
import com.android.systemui.recents.events.component.RecentsVisibilityChangedEvent;
import com.android.systemui.recents.misc.SystemServicesProxy;
import com.android.systemui.recents.model.Task;
@@ -53,7 +54,8 @@
private View mEmptyView;
private boolean mAwaitingFirstLayout = true;
private Rect mSystemInsets = new Rect();
-
+ private RecentsTvTransitionHelper mTransitionHelper;
+ private Handler mHandler;
public RecentsTvView(Context context) {
this(context, null);
@@ -75,6 +77,8 @@
LayoutInflater inflater = LayoutInflater.from(context);
mEmptyView = inflater.inflate(R.layout.recents_empty, this, false);
addView(mEmptyView);
+ mHandler = new Handler();
+ mTransitionHelper = new RecentsTvTransitionHelper(mContext, mHandler);
}
public void setTaskStack(TaskStack stack) {
@@ -209,6 +213,11 @@
/**** EventBus Events ****/
+ public final void onBusEvent(LaunchTvTaskEvent event) {
+ mTransitionHelper.launchTaskFromRecents(mStack, event.task, mTaskStackHorizontalView,
+ event.taskView, event.targetTaskBounds, event.targetTaskStack);
+ }
+
public final void onBusEvent(DismissRecentsToHomeAnimationStarted event) {
// If we are going home, cancel the previous task's window transition
EventBus.getDefault().send(new CancelEnterRecentsWindowAnimationEvent(null));
diff --git a/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskCardView.java b/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskCardView.java
index e275f22..7d8a3ce 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskCardView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskCardView.java
@@ -16,20 +16,20 @@
package com.android.systemui.recents.tv.views;
import android.content.Context;
+import android.graphics.Rect;
import android.util.AttributeSet;
import android.widget.ImageView;
-import android.widget.RelativeLayout;
+import android.widget.LinearLayout;
import android.widget.TextView;
import com.android.systemui.R;
-import com.android.systemui.recents.model.Task;
import com.android.systemui.recents.tv.animations.ViewFocusAnimator;
+import com.android.systemui.recents.model.Task;
-public class TaskCardView extends RelativeLayout {
+public class TaskCardView extends LinearLayout {
private ImageView mThumbnailView;
private TextView mTitleTextView;
- private TextView mContentTextView;
private ImageView mBadgeView;
private Task mTask;
@@ -52,7 +52,6 @@
protected void onFinishInflate() {
mThumbnailView = (ImageView) findViewById(R.id.card_view_thumbnail);
mTitleTextView = (TextView) findViewById(R.id.card_title_text);
- mContentTextView = (TextView) findViewById(R.id.card_content_text);
mBadgeView = (ImageView) findViewById(R.id.card_extra_badge);
}
@@ -60,11 +59,27 @@
mTask = task;
mThumbnailView.setImageBitmap(task.thumbnail);
mTitleTextView.setText(task.title);
- mContentTextView.setText(task.contentDescription);
mBadgeView.setImageDrawable(task.icon);
}
public Task getTask() {
return mTask;
}
+
+ @Override
+ public void getFocusedRect(Rect r) {
+ mThumbnailView.getFocusedRect(r);
+ }
+
+ public Rect getFocusedRect() {
+ Rect r = new Rect();
+ getFocusedRect(r);
+ return r;
+ }
+
+ public Rect getGlobalRect() {
+ Rect r = new Rect();
+ getGlobalVisibleRect(r);
+ return r;
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskStackHorizontalGridView.java b/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskStackHorizontalGridView.java
index 58ec852..4458639 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskStackHorizontalGridView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskStackHorizontalGridView.java
@@ -15,7 +15,6 @@
*/
package com.android.systemui.recents.tv.views;
-
import android.content.Context;
import android.support.v17.leanback.widget.HorizontalGridView;
import android.util.AttributeSet;
@@ -36,13 +35,17 @@
/**
* Horizontal Grid View Implementation to show the Task Stack for TV.
*/
-public class TaskStackHorizontalGridView extends HorizontalGridView implements TaskStackCallbacks{
+public class TaskStackHorizontalGridView extends HorizontalGridView implements TaskStackCallbacks {
private TaskStack mStack;
private ArrayList<TaskCardView> mTaskViews = new ArrayList<>();
private Task mFocusedTask;
+ public TaskStackHorizontalGridView(Context context) {
+ this(context, null);
+ }
+
public TaskStackHorizontalGridView(Context context, AttributeSet attrs) {
super(context, attrs);
}
@@ -64,8 +67,6 @@
* Resets this view for reuse.
*/
public void reset() {
- // Reset the focused task
- resetFocusedTask(getFocusedTask());
requestLayout();
}
@@ -73,12 +74,6 @@
* @param task - Task to reset
*/
private void resetFocusedTask(Task task) {
- if (task != null) {
- TaskCardView tv = getChildViewForTask(task);
- if (tv != null) {
- tv.requestFocus();
- }
- }
mFocusedTask = null;
}
@@ -107,6 +102,9 @@
* @return - The focused task.
*/
public Task getFocusedTask() {
+ if (findFocus() != null) {
+ mFocusedTask = ((TaskCardView)findFocus()).getTask();
+ }
return mFocusedTask;
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskStackHorizontalViewAdapter.java b/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskStackHorizontalViewAdapter.java
index f154331..fba424e 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskStackHorizontalViewAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskStackHorizontalViewAdapter.java
@@ -16,7 +16,6 @@
package com.android.systemui.recents.tv.views;
import android.app.Activity;
-import android.app.ActivityManagerNative;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
@@ -24,15 +23,20 @@
import android.view.ViewGroup;
import com.android.systemui.R;
+import com.android.systemui.recents.events.EventBus;
+import com.android.systemui.recents.events.activity.LaunchTvTaskEvent;
import com.android.systemui.recents.model.Task;
import java.util.ArrayList;
import java.util.List;
+import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
+
public class TaskStackHorizontalViewAdapter extends
RecyclerView.Adapter<TaskStackHorizontalViewAdapter.ViewHolder> {
- private static final String TAG = "TaskStackHorizontalViewAdapter";
+ //Full class name is 30 characters
+ private static final String TAG = "TaskStackViewAdapter";
private List<Task> mTaskList;
static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
@@ -54,7 +58,8 @@
@Override
public void onClick(View v) {
try {
- ActivityManagerNative.getDefault().startActivityFromRecents(mTask.key.id, null);
+ EventBus.getDefault().send(new LaunchTvTaskEvent(mTaskCardView, mTask,
+ null, INVALID_STACK_ID));
((Activity)(v.getContext())).finish();
} catch (Exception e) {
Log.e(TAG, v.getContext()
@@ -73,11 +78,12 @@
mTaskList.addAll(tasks);
notifyDataSetChanged();
}
+
@Override
public TaskStackHorizontalViewAdapter.ViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
View view = LayoutInflater.from(parent.getContext())
- .inflate(R.layout.recents_task_card_view, parent, false);
+ .inflate(R.layout.recents_tv_task_card_view, parent, false);
ViewHolder viewHolder = new ViewHolder(view);
return viewHolder;
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/FreeformWorkspaceLayoutAlgorithm.java b/packages/SystemUI/src/com/android/systemui/recents/views/FreeformWorkspaceLayoutAlgorithm.java
index 4359101..72b914c 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/FreeformWorkspaceLayoutAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/FreeformWorkspaceLayoutAlgorithm.java
@@ -37,6 +37,13 @@
private int mTaskPadding;
public FreeformWorkspaceLayoutAlgorithm(Context context) {
+ reloadOnConfigurationChange(context);
+ }
+
+ /**
+ * Reloads the layout for the current configuration.
+ */
+ public void reloadOnConfigurationChange(Context context) {
// This is applied to the edges of each task
mTaskPadding = context.getResources().getDimensionPixelSize(
R.dimen.recents_freeform_workspace_task_padding) / 2;
@@ -72,8 +79,7 @@
}
// Bound the task width to the workspace width so that at the worst case, it will
// fit its own row
- normalizedTaskWidths[i] = Math.min(rowTaskWidth,
- normalizedWorkspaceWidth);
+ normalizedTaskWidths[i] = Math.min(rowTaskWidth, normalizedWorkspaceWidth);
}
// Determine the scale to best fit each of the tasks in the workspace
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java
index 37b2859..e5022a4 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java
@@ -105,9 +105,6 @@
animStartedListener = new ActivityOptions.OnAnimationStartedListener() {
@Override
public void onAnimationStarted() {
- // If we are launching into another task, cancel the previous task's
- // window transition
- EventBus.getDefault().send(new CancelEnterRecentsWindowAnimationEvent(task));
EventBus.getDefault().send(new ExitRecentsWindowFirstAnimationFrameEvent());
if (screenPinningRequested) {
@@ -149,6 +146,10 @@
animStartedListener);
}
}
+
+ // If we are launching into another task, cancel the previous task's
+ // window transition
+ EventBus.getDefault().send(new CancelEnterRecentsWindowAnimationEvent(task));
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
index 5dde926..10f491e 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
@@ -192,7 +192,7 @@
// If we are already occluded by the app, then just set the default background scrim now.
// Otherwise, defer until the enter animation completes to animate the scrim with the
// tasks for the home animation.
- if (launchState.launchedWhileDocking || launchState.launchedFromAppWithThumbnail
+ if (launchState.launchedWhileDocking || launchState.launchedFromApp
|| mStack.getTaskCount() == 0) {
mBackgroundScrim.setAlpha((int) (DEFAULT_SCRIM_ALPHA * 255));
} else {
@@ -671,7 +671,7 @@
public final void onBusEvent(EnterRecentsWindowAnimationCompletedEvent event) {
RecentsActivityLaunchState launchState = Recents.getConfiguration().getLaunchState();
- if (!launchState.launchedWhileDocking && !launchState.launchedFromAppWithThumbnail
+ if (!launchState.launchedWhileDocking && !launchState.launchedFromApp
&& mStack.getTaskCount() > 0) {
animateBackgroundScrim(DEFAULT_SCRIM_ALPHA,
TaskStackAnimationHelper.ENTER_FROM_HOME_TRANSLATION_DURATION);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackAnimationHelper.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackAnimationHelper.java
index d152010..758f4d82 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackAnimationHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackAnimationHelper.java
@@ -56,8 +56,8 @@
/**
* Callback to start the animation for the launch target {@link TaskView}.
*/
- void onStartLaunchTargetEnterAnimation(int duration, boolean screenPinningEnabled,
- ReferenceCountedTrigger postAnimationTrigger);
+ void onStartLaunchTargetEnterAnimation(TaskViewTransform transform, int duration,
+ boolean screenPinningEnabled, ReferenceCountedTrigger postAnimationTrigger);
/**
* Callback to start the animation for the launch target {@link TaskView} when it is
@@ -141,7 +141,7 @@
tv.setVisibility(View.INVISIBLE);
} else if (launchState.launchedHasConfigurationChanged) {
// Just load the views as-is
- } else if (launchState.launchedFromAppWithThumbnail) {
+ } else if (launchState.launchedFromApp) {
if (task.isLaunchTarget) {
tv.onPrepareLaunchTargetForEnterAnimation();
} else if (currentTaskOccludesLaunchTarget) {
@@ -205,10 +205,11 @@
stackLayout.getStackTransform(task, stackScroller.getStackScroll(), mTmpTransform,
null);
- if (launchState.launchedFromAppWithThumbnail) {
+ if (launchState.launchedFromApp) {
if (task.isLaunchTarget) {
- tv.onStartLaunchTargetEnterAnimation(taskViewEnterFromAppDuration,
- mStackView.mScreenPinningEnabled, postAnimationTrigger);
+ tv.onStartLaunchTargetEnterAnimation(mTmpTransform,
+ taskViewEnterFromAppDuration, mStackView.mScreenPinningEnabled,
+ postAnimationTrigger);
} else {
// Animate the task up if it was occluding the launch target
if (currentTaskOccludesLaunchTarget) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java
index 261b6f6..b60fca8c1 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java
@@ -29,6 +29,7 @@
import com.android.systemui.recents.Recents;
import com.android.systemui.recents.RecentsActivityLaunchState;
import com.android.systemui.recents.RecentsConfiguration;
+import com.android.systemui.recents.RecentsDebugFlags;
import com.android.systemui.recents.misc.FreePathInterpolator;
import com.android.systemui.recents.misc.SystemServicesProxy;
import com.android.systemui.recents.misc.Utilities;
@@ -36,6 +37,7 @@
import com.android.systemui.recents.model.TaskStack;
import java.util.ArrayList;
+import java.util.List;
/**
* Used to describe a visible range that can be normalized to [0, 1].
@@ -220,6 +222,10 @@
private Range mUnfocusedRange;
private Range mFocusedRange;
+ // The initial offset from the top of the stack
+ @ViewDebug.ExportedProperty(category="recents")
+ private int mInitialTopPeekHeight;
+
// The offset from the top when scrolled to the top of the stack
@ViewDebug.ExportedProperty(category="recents")
private int mFocusedTopPeekHeight;
@@ -231,6 +237,10 @@
@ViewDebug.ExportedProperty(category="recents")
private int mStackTopOffset;
+ // The height of the header bar
+ @ViewDebug.ExportedProperty(category="recents")
+ private int mHeaderBarHeight;
+
// The offset from the bottom of the stack to the bottom of the bounds when the stack is
// scrolled to the front
@ViewDebug.ExportedProperty(category="recents")
@@ -249,6 +259,9 @@
private FreePathInterpolator mUnfocusedDimCurveInterpolator;
private FreePathInterpolator mFocusedDimCurveInterpolator;
+ // Indexed from the front of the stack, the normalized x in the unfocused range for each task
+ private float[] mInitialNormX;
+
// The state of the stack focus (0..1), which controls the transition of the stack from the
// focused to non-focused state
@ViewDebug.ExportedProperty(category="recents")
@@ -292,23 +305,32 @@
TaskViewTransform mFrontOfStackTransform = new TaskViewTransform();
public TaskStackLayoutAlgorithm(Context context, TaskStackLayoutAlgorithmCallbacks cb) {
- Resources res = context.getResources();
mContext = context;
mCb = cb;
+ mFreeformLayoutAlgorithm = new FreeformWorkspaceLayoutAlgorithm(context);
+ reloadOnConfigurationChange(context);
+ }
+ /**
+ * Reloads the layout for the current configuration.
+ */
+ public void reloadOnConfigurationChange(Context context) {
+ Resources res = context.getResources();
mFocusedRange = new Range(res.getFloat(R.integer.recents_layout_focused_range_min),
res.getFloat(R.integer.recents_layout_focused_range_max));
mUnfocusedRange = new Range(res.getFloat(R.integer.recents_layout_unfocused_range_min),
res.getFloat(R.integer.recents_layout_unfocused_range_max));
- mFocusState = getDefaultFocusState();
+ mFocusState = getInitialFocusState();
+ mInitialTopPeekHeight = res.getDimensionPixelSize(R.dimen.recents_initial_top_peek_size);
mFocusedTopPeekHeight =
res.getDimensionPixelSize(R.dimen.recents_layout_focused_top_peek_size);
mFocusedBottomTaskPeekHeight =
res.getDimensionPixelSize(R.dimen.recents_layout_focused_bottom_task_peek_size);
+ mHeaderBarHeight = res.getDimensionPixelSize(R.dimen.recents_task_bar_height);
mMinTranslationZ = res.getDimensionPixelSize(R.dimen.recents_task_view_z_min);
mMaxTranslationZ = res.getDimensionPixelSize(R.dimen.recents_task_view_z_max);
- mFreeformLayoutAlgorithm = new FreeformWorkspaceLayoutAlgorithm(context);
+ mFreeformLayoutAlgorithm.reloadOnConfigurationChange(context);
}
/**
@@ -316,7 +338,7 @@
*/
public void reset() {
mTaskIndexOverrideMap.clear();
- setFocusState(getDefaultFocusState());
+ setFocusState(getInitialFocusState());
}
/**
@@ -439,46 +461,87 @@
mTaskIndexMap.put(task.key.id, i);
}
- // Calculate the min/max scroll
- if (getDefaultFocusState() > 0f) {
- mMinScrollP = 0;
- mMaxScrollP = Math.max(mMinScrollP, mNumStackTasks - 1);
- } else {
- if (!ssp.hasFreeformWorkspaceSupport() && mNumStackTasks == 1) {
- mMinScrollP = mMaxScrollP = 0;
- } else {
- float bottomOffsetPct = (float) (mStackBottomOffset + mTaskRect.height()) /
- mStackRect.height();
- float normX = mUnfocusedCurveInterpolator.getX(bottomOffsetPct);
- mMinScrollP = 0;
- mMaxScrollP = Math.max(mMinScrollP, (mNumStackTasks - 1) -
- Math.max(0, mUnfocusedRange.getAbsoluteX(normX)));
- }
- }
-
+ // Update the freeform tasks
if (!freeformTasks.isEmpty()) {
mFreeformLayoutAlgorithm.update(freeformTasks, this);
- mInitialScrollP = mMaxScrollP;
- } else {
- Task launchTask = stack.getLaunchTarget();
- int launchTaskIndex = launchTask != null
- ? stack.indexOfStackTask(launchTask)
- : mNumStackTasks - 1;
- if (!ssp.hasFreeformWorkspaceSupport() && mNumStackTasks == 1) {
- mInitialScrollP = mMinScrollP;
- } else if (getDefaultFocusState() > 0f) {
- if (launchState.launchedFromHome) {
- mInitialScrollP = Utilities.clamp(launchTaskIndex, mMinScrollP, mMaxScrollP);
- } else {
- mInitialScrollP = Utilities.clamp(launchTaskIndex - 1, mMinScrollP,
- mMaxScrollP);
- }
+ }
+
+ // Calculate the min/max/initial scroll
+ Task launchTask = stack.getLaunchTarget();
+ int launchTaskIndex = launchTask != null
+ ? stack.indexOfStackTask(launchTask)
+ : mNumStackTasks - 1;
+ if (getInitialFocusState() == STATE_FOCUSED) {
+ mMinScrollP = 0;
+ mMaxScrollP = Math.max(mMinScrollP, mNumStackTasks - 1);
+ if (launchState.launchedFromHome) {
+ mInitialScrollP = Utilities.clamp(launchTaskIndex, mMinScrollP, mMaxScrollP);
} else {
- float offsetPct = (float) (mTaskRect.height() / 3) / mStackRect.height();
- float normX = mUnfocusedCurveInterpolator.getX(offsetPct);
- mInitialScrollP = Utilities.clamp(launchTaskIndex -
- mUnfocusedRange.getAbsoluteX(normX), mMinScrollP, mMaxScrollP);
+ mInitialScrollP = Utilities.clamp(launchTaskIndex - 1, mMinScrollP, mMaxScrollP);
}
+ } else if (!ssp.hasFreeformWorkspaceSupport() && mNumStackTasks == 1) {
+ // If there is one stack task, ignore the min/max/initial scroll positions
+ mMinScrollP = 0;
+ mMaxScrollP = 0;
+ mInitialScrollP = 0;
+ } else {
+ // Set the max scroll to be the point where the front most task is visible with the
+ // stack bottom offset
+ int maxBottomOffset = mStackBottomOffset + mTaskRect.height();
+ float maxBottomOffsetPct = (float) maxBottomOffset / mStackRect.height();
+ float maxBottomNormX = mUnfocusedCurveInterpolator.getX(maxBottomOffsetPct);
+ mUnfocusedRange.offset(0f);
+ mMinScrollP = 0;
+ mMaxScrollP = Math.max(mMinScrollP, (mNumStackTasks - 1) -
+ Math.max(0, mUnfocusedRange.getAbsoluteX(maxBottomNormX)));
+ boolean scrollToFront = launchState.launchedFromHome ||
+ launchState.launchedFromAppDocked;
+ if (scrollToFront) {
+ mInitialScrollP = Utilities.clamp(launchTaskIndex, mMinScrollP, mMaxScrollP);
+ } else {
+ mInitialScrollP = Utilities.clamp(launchTaskIndex - 1, mMinScrollP, mMaxScrollP);
+ }
+
+ // Set the initial scroll to the predefined state (which differs from the stack)
+ int initialPeekOffset = mStackRect.height() - mInitialTopPeekHeight;
+ float initialPeekOffsetPct = (float) initialPeekOffset / mStackRect.height();
+ float initialPeekOffsetNormX = mUnfocusedCurveInterpolator.getX(initialPeekOffsetPct);
+ float initialFocusedOffset = mStackRect.height() - mInitialTopPeekHeight -
+ (mHeaderBarHeight * 1f) + 1;
+ float initialFocusedOffsetPct = (float) initialFocusedOffset / mStackRect.height();
+ float initialFocusedNormX = mUnfocusedCurveInterpolator.getX(initialFocusedOffsetPct);
+ int initialBottomOffset = mStackBottomOffset + mHeaderBarHeight;
+ float initialBottomOffsetPct = (float) initialBottomOffset / mStackRect.height();
+ float initialBottomNormX = mUnfocusedCurveInterpolator.getX(initialBottomOffsetPct);
+ /*
+ // If we want to offset the top card slightly
+ mInitialNormX = scrollToFront
+ ? new float[] { initialFocusedNormX, initialPeekOffsetNormX, 0f }
+ : new float[] { initialBottomNormX, initialFocusedNormX,
+ initialPeekOffsetNormX, 0f };
+ */
+ mInitialNormX = scrollToFront
+ ? new float[] { initialFocusedNormX, initialPeekOffsetNormX, 0f }
+ : new float[] { initialBottomNormX, 0.5f, 0f };
+ }
+ }
+
+ public void updateToInitialState(List<Task> tasks) {
+ if (mInitialNormX == null) {
+ return;
+ }
+
+ RecentsActivityLaunchState launchState = Recents.getConfiguration().getLaunchState();
+ mUnfocusedRange.offset(0f);
+ int taskCount = tasks.size();
+ for (int i = taskCount - 1; i >= 0; i--) {
+ int indexFromFront = taskCount - i - 1;
+ if (indexFromFront >= mInitialNormX.length) {
+ break;
+ }
+ float newTaskProgress = mInitialScrollP +
+ mUnfocusedRange.getAbsoluteX(mInitialNormX[indexFromFront]);
+ mTaskIndexOverrideMap.put(tasks.get(i).key.id, newTaskProgress);
}
}
@@ -500,6 +563,10 @@
}
}
+ public void clearUnfocusedTaskOverrides() {
+ mTaskIndexOverrideMap.clear();
+ }
+
/**
* Updates this stack when a scroll happens.
*/
@@ -523,7 +590,7 @@
} else {
// Scrolling override x away from x, we should still move the scroll towards x
float deltaX = overrideX - x;
- newOverrideX = Math.signum(deltaX) * (Math.abs(deltaX) - deltaScroll);
+ newOverrideX = Math.signum(deltaX) * (Math.abs(deltaX) - Math.abs(deltaScroll));
mTaskIndexOverrideMap.put(taskId, x + newOverrideX);
}
}
@@ -532,8 +599,13 @@
/**
* Returns the default focus state.
*/
- public int getDefaultFocusState() {
- return STATE_FOCUSED;
+ public int getInitialFocusState() {
+ RecentsDebugFlags debugFlags = Recents.getDebugFlags();
+ if (debugFlags.isPagingEnabled()) {
+ return STATE_FOCUSED;
+ } else {
+ return STATE_UNFOCUSED;
+ }
}
/**
@@ -577,7 +649,7 @@
// Otherwise, walk backwards in the stack and count the number of tasks and visible
// thumbnails and add that to the total freeform task count
TaskViewTransform tmpTransform = new TaskViewTransform();
- Range currentRange = getDefaultFocusState() > 0f ? mFocusedRange : mUnfocusedRange;
+ Range currentRange = getInitialFocusState() > 0f ? mFocusedRange : mUnfocusedRange;
currentRange.offset(mInitialScrollP);
int taskBarHeight = mContext.getResources().getDimensionPixelSize(
R.dimen.recents_task_bar_height);
@@ -635,11 +707,19 @@
public TaskViewTransform getStackTransform(Task task, float stackScroll,
TaskViewTransform transformOut, TaskViewTransform frontTransform) {
return getStackTransform(task, stackScroll, mFocusState, transformOut, frontTransform,
- false /* forceUpdate */);
+ false /* forceUpdate */, false /* ignoreTaskOverrides */);
+ }
+
+ public TaskViewTransform getStackTransform(Task task, float stackScroll,
+ TaskViewTransform transformOut, TaskViewTransform frontTransform,
+ boolean ignoreTaskOverrides) {
+ return getStackTransform(task, stackScroll, mFocusState, transformOut, frontTransform,
+ false /* forceUpdate */, ignoreTaskOverrides);
}
public TaskViewTransform getStackTransform(Task task, float stackScroll, int focusState,
- TaskViewTransform transformOut, TaskViewTransform frontTransform, boolean forceUpdate) {
+ TaskViewTransform transformOut, TaskViewTransform frontTransform, boolean forceUpdate,
+ boolean ignoreTaskOverrides) {
if (mFreeformLayoutAlgorithm.isTransformAvailable(task, this)) {
mFreeformLayoutAlgorithm.getTransform(task, transformOut, this);
return transformOut;
@@ -649,7 +729,9 @@
transformOut.reset();
return transformOut;
}
- float taskProgress = getStackScrollForTask(task);
+ float taskProgress = ignoreTaskOverrides
+ ? mTaskIndexMap.get(task.key.id, 0)
+ : getStackScrollForTask(task);
getStackTransform(taskProgress, stackScroll, focusState, transformOut,
frontTransform, false /* ignoreSingleTaskCase */, forceUpdate);
return transformOut;
@@ -851,8 +933,8 @@
// The unfocused dim interpolator starts at max dim, reduces to zero at 0.5 (the focused
// task), then goes back to max dim towards the front of the stack
p.moveTo(0f, MAX_DIM);
- p.cubicTo(0f, 0.1f, 0.4f, 0f, 0.5f, 0f);
- p.cubicTo(0.6f, 0f, 0.9f, MAX_DIM - 0.1f, 1f, MAX_DIM / 2f);
+ p.cubicTo(0.1f, MAX_DIM, 0.4f, 0.0f, 0.5f, 0f);
+ p.cubicTo(0.6f, 0f, 0.9f, MAX_DIM / 2f, 1f, MAX_DIM / 2f);
return p;
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
index e1a81c8..c2bfc28 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -35,7 +35,6 @@
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.MutableBoolean;
-import android.util.SparseBooleanArray;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
@@ -56,6 +55,7 @@
import com.android.systemui.recents.RecentsDebugFlags;
import com.android.systemui.recents.events.EventBus;
import com.android.systemui.recents.events.activity.CancelEnterRecentsWindowAnimationEvent;
+import com.android.systemui.recents.events.activity.ConfigurationChangedEvent;
import com.android.systemui.recents.events.activity.DismissRecentsToHomeAnimationStarted;
import com.android.systemui.recents.events.activity.EnterRecentsTaskStackAnimationCompletedEvent;
import com.android.systemui.recents.events.activity.EnterRecentsWindowAnimationCompletedEvent;
@@ -73,7 +73,6 @@
import com.android.systemui.recents.events.ui.AllTaskViewsDismissedEvent;
import com.android.systemui.recents.events.ui.DeleteTaskDataEvent;
import com.android.systemui.recents.events.ui.DismissTaskViewEvent;
-import com.android.systemui.recents.events.ui.StackViewScrolledEvent;
import com.android.systemui.recents.events.ui.TaskViewDismissedEvent;
import com.android.systemui.recents.events.ui.UpdateFreeformTaskViewVisibilityEvent;
import com.android.systemui.recents.events.ui.UserInteractionEvent;
@@ -274,10 +273,18 @@
}
/** Returns the task stack. */
- TaskStack getStack() {
+ public TaskStack getStack() {
return mStack;
}
+ /**
+ * Updates this TaskStackView to the initial state.
+ */
+ public void updateToInitialState() {
+ mStackScroller.setStackScrollToInitialState();
+ mLayoutAlgorithm.updateToInitialState(mStack.getStackTasks());
+ }
+
/** Updates the list of task views */
void updateTaskViewsList() {
mTaskViews.clear();
@@ -355,7 +362,6 @@
mAwaitingFirstLayout = true;
mEnterAnimationComplete = false;
mUIDozeTrigger.stopDozing();
- mUIDozeTrigger.resetTrigger();
mStackScroller.reset();
mLayoutAlgorithm.reset();
readSystemFlags();
@@ -410,7 +416,7 @@
*/
int[] computeVisibleTaskTransforms(ArrayList<TaskViewTransform> taskTransforms,
ArrayList<Task> tasks, float curStackScroll, float targetStackScroll,
- ArraySet<Task.TaskKey> ignoreTasksSet) {
+ ArraySet<Task.TaskKey> ignoreTasksSet, boolean ignoreTaskOverrides) {
int taskCount = tasks.size();
int[] visibleTaskRange = mTmpIntPair;
visibleTaskRange[0] = -1;
@@ -430,7 +436,7 @@
// Calculate the current and (if necessary) the target transform for the task
transform = mLayoutAlgorithm.getStackTransform(task, curStackScroll,
- taskTransforms.get(i), frontTransform);
+ taskTransforms.get(i), frontTransform, ignoreTaskOverrides);
if (useTargetStackScroll && !transform.visible) {
// If we have a target stack scroll and the task is not currently visible, then we
// just update the transform at the new scroll
@@ -468,11 +474,13 @@
/**
* Binds the visible {@link TaskView}s at the given target scroll.
- *
- * @see #bindVisibleTaskViews(float, ArraySet<Task.TaskKey>)
*/
void bindVisibleTaskViews(float targetStackScroll) {
- bindVisibleTaskViews(targetStackScroll, mIgnoreTasks);
+ bindVisibleTaskViews(targetStackScroll, mIgnoreTasks, false /* ignoreTaskOverrides */);
+ }
+
+ void bindVisibleTaskViews(float targetStackScroll, boolean ignoreTaskOverrides) {
+ bindVisibleTaskViews(targetStackScroll, mIgnoreTasks, ignoreTaskOverrides);
}
/**
@@ -487,12 +495,16 @@
* target stack scroll.
* @param ignoreTasksSet The set of tasks to ignore in this rebinding of the visible
* {@link TaskView}s
+ * @param ignoreTaskOverrides If set, the visible task computation will get the transforms for
+ * tasks at their non-overridden task progress
*/
- void bindVisibleTaskViews(float targetStackScroll, ArraySet<Task.TaskKey> ignoreTasksSet) {
+ void bindVisibleTaskViews(float targetStackScroll, ArraySet<Task.TaskKey> ignoreTasksSet,
+ boolean ignoreTaskOverrides) {
// Get all the task transforms
ArrayList<Task> tasks = mStack.getStackTasks();
int[] visibleTaskRange = computeVisibleTaskTransforms(mCurrentTaskTransforms, tasks,
- mStackScroller.getStackScroll(), targetStackScroll, ignoreTasksSet);
+ mStackScroller.getStackScroll(), targetStackScroll, ignoreTasksSet,
+ ignoreTaskOverrides);
// Return all the invisible children to the pool
mTmpTaskViewMap.clear();
@@ -605,7 +617,8 @@
cancelAllTaskViewAnimations();
// Synchronize the current set of TaskViews
- bindVisibleTaskViews(mStackScroller.getStackScroll(), ignoreTasksSet);
+ bindVisibleTaskViews(mStackScroller.getStackScroll(), ignoreTasksSet,
+ false /* ignoreTaskOverrides */);
// Animate them to their final transforms with the given animation
List<TaskView> taskViews = getTaskViews();
@@ -657,7 +670,8 @@
transform.fillIn(tv);
} else {
mLayoutAlgorithm.getStackTransform(task, mStackScroller.getStackScroll(),
- focusState, transform, null, true /* forceUpdate */);
+ focusState, transform, null, true /* forceUpdate */,
+ false /* ignoreTaskOverrides */);
}
transform.visible = true;
}
@@ -674,7 +688,7 @@
Task task = tasks.get(i);
TaskViewTransform transform = transformsOut.get(i);
mLayoutAlgorithm.getStackTransform(task, stackScroll, focusState, transform, null,
- true /* forceUpdate */);
+ true /* forceUpdate */, true /* ignoreTaskOverrides */);
transform.visible = true;
}
}
@@ -759,9 +773,7 @@
}
}
tv.getViewBounds().setClipBottom(clipBottom);
- if (!config.useHardwareLayers) {
- tv.mThumbnailView.updateThumbnailVisibility(clipBottom - tv.getPaddingBottom());
- }
+ tv.mThumbnailView.updateThumbnailVisibility(clipBottom - tv.getPaddingBottom());
prevVisibleTv = tv;
}
mTaskViewsClipDirty = false;
@@ -860,6 +872,7 @@
cancelAllTaskViewAnimations();
}
+ mLayoutAlgorithm.clearUnfocusedTaskOverrides();
willScroll = mAnimationHelper.startScrollToFocusedTaskAnimation(newFocusedTask,
requestViewFocus);
} else {
@@ -1162,11 +1175,16 @@
// If this is the first layout, then scroll to the front of the stack, then update the
// TaskViews with the stack so that we can lay them out
- if (mAwaitingFirstLayout) {
- mStackScroller.setStackScrollToInitialState();
+ // TODO: The second check is a workaround for wacky layouts that we get while docking via
+ // long pressing the recents button
+ if (mAwaitingFirstLayout ||
+ (mStackScroller.getStackScroll() == mLayoutAlgorithm.mInitialScrollP)) {
+ updateToInitialState();
}
+
// Rebind all the views, including the ignore ones
- bindVisibleTaskViews(mStackScroller.getStackScroll(), EMPTY_TASK_SET);
+ bindVisibleTaskViews(mStackScroller.getStackScroll(), EMPTY_TASK_SET,
+ false /* ignoreTaskOverrides */);
// Measure each of the TaskViews
mTmpTaskViews.clear();
@@ -1458,7 +1476,7 @@
Recents.getTaskLoader().loadTaskData(task, true /* fetchAndInvalidateThumbnails */);
// If the doze trigger has already fired, then update the state for this task view
- if (mUIDozeTrigger.hasTriggered()) {
+ if (mUIDozeTrigger.isAsleep()) {
tv.setNoUserInteractionState();
}
@@ -1859,6 +1877,12 @@
});
}
+ public final void onBusEvent(ConfigurationChangedEvent event) {
+ mLayoutAlgorithm.reloadOnConfigurationChange(getContext());
+ mLayoutAlgorithm.initialize(mStackBounds,
+ TaskStackLayoutAlgorithm.StackState.getStackStateForStack(mStack));
+ }
+
/**
* Removes the task from the stack, and updates the focus to the next task in the stack if the
* removed TaskView was focused.
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewScroller.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewScroller.java
index 333df9d..ad46abd 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewScroller.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewScroller.java
@@ -115,13 +115,8 @@
* @return whether the stack progress changed.
*/
public boolean setStackScrollToInitialState() {
- SystemServicesProxy ssp = Recents.getSystemServices();
float prevStackScrollP = mStackScrollP;
- if (ssp.hasDockedTask()) {
- setStackScroll(mLayoutAlgorithm.mMaxScrollP);
- } else {
- setStackScroll(mLayoutAlgorithm.mInitialScrollP);
- }
+ setStackScroll(mLayoutAlgorithm.mInitialScrollP);
return Float.compare(prevStackScrollP, mStackScrollP) != 0;
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
index 20933ee..52f8fc8 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
@@ -446,7 +446,7 @@
}
// Pick up the newly visible views, not including the deleting tasks
- mSv.bindVisibleTaskViews(newStackScroll);
+ mSv.bindVisibleTaskViews(newStackScroll, true /* ignoreTaskOverrides */);
// Get the final set of task transforms (with task removed)
mSv.getLayoutTaskTransforms(newStackScroll, TaskStackLayoutAlgorithm.STATE_UNFOCUSED,
@@ -486,6 +486,7 @@
mSv.getScroller().setStackScroll(mTargetStackScroll, null);
// Update the focus state to the final focus state
mSv.getStackAlgorithm().setFocusState(TaskStackLayoutAlgorithm.STATE_UNFOCUSED);
+ mSv.getStackAlgorithm().clearUnfocusedTaskOverrides();
// Remove the task view from the stack
EventBus.getDefault().send(new TaskViewDismissedEvent(tv.getTask(), tv));
// Stop tracking this deletion animation
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
index 0c78e6a..e9c7ac6 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
@@ -77,6 +77,24 @@
/**
* The dim overlay is generally calculated from the task progress, but occasionally (like when
+ * launching) needs to be animated independently of the task progress. This call is only used
+ * when animating the task into Recents, when the header dim is already applied
+ */
+ public static final Property<TaskView, Float> DIM_ALPHA_WITHOUT_HEADER =
+ new FloatProperty<TaskView>("dimAlphaWithoutHeader") {
+ @Override
+ public void setValue(TaskView tv, float dimAlpha) {
+ tv.setDimAlphaWithoutHeader(dimAlpha);
+ }
+
+ @Override
+ public Float get(TaskView tv) {
+ return tv.getDimAlpha();
+ }
+ };
+
+ /**
+ * The dim overlay is generally calculated from the task progress, but occasionally (like when
* launching) needs to be animated independently of the task progress.
*/
public static final Property<TaskView, Float> DIM_ALPHA =
@@ -388,21 +406,17 @@
* Sets the current dim.
*/
public void setDimAlpha(float dimAlpha) {
- RecentsConfiguration config = Recents.getConfiguration();
-
- int dimAlphaInt = (int) (dimAlpha * 255);
mDimAlpha = dimAlpha;
- if (config.useHardwareLayers) {
- // Defer setting hardware layers if we have not yet measured, or there is no dim to draw
- if (getMeasuredWidth() > 0 && getMeasuredHeight() > 0) {
- mDimColorFilter.setColor(Color.argb(dimAlphaInt, 0, 0, 0));
- mDimLayerPaint.setColorFilter(mDimColorFilter);
- mContent.setLayerType(LAYER_TYPE_HARDWARE, mDimLayerPaint);
- }
- } else {
- mThumbnailView.setDimAlpha(dimAlpha);
- mHeaderView.setDimAlpha(dimAlpha);
- }
+ mThumbnailView.setDimAlpha(dimAlpha);
+ mHeaderView.setDimAlpha(dimAlpha);
+ }
+
+ /**
+ * Sets the current dim without updating the header's dim.
+ */
+ public void setDimAlphaWithoutHeader(float dimAlpha) {
+ mDimAlpha = dimAlpha;
+ mThumbnailView.setDimAlpha(dimAlpha);
}
/**
@@ -413,25 +427,6 @@
}
/**
- * Animates the dim to the given value.
- */
- void animateDimAlpha(float toDimAlpha, AnimationProps animation) {
- // Animate the dim into view as well
- if (Float.compare(toDimAlpha, getDimAlpha()) != 0) {
- Animator anim = animation.apply(AnimationProps.DIM_ALPHA, ObjectAnimator.ofFloat(this,
- DIM_ALPHA, getDimAlpha(), toDimAlpha));
- if (animation.getListener() != null) {
- anim.addListener(animation.getListener());
- }
- anim.start();
- } else {
- if (animation.getListener() != null) {
- animation.getListener().onAnimationEnd(null);
- }
- }
- }
-
- /**
* Explicitly sets the focused state of this task.
*/
public void setFocusedState(boolean isFocused, boolean requestViewFocus) {
@@ -517,18 +512,20 @@
@Override
public void onPrepareLaunchTargetForEnterAnimation() {
// These values will be animated in when onStartLaunchTargetEnterAnimation() is called
- setDimAlpha(0);
+ setDimAlphaWithoutHeader(0);
mActionButtonView.setAlpha(0f);
}
@Override
- public void onStartLaunchTargetEnterAnimation(int duration, boolean screenPinningEnabled,
- ReferenceCountedTrigger postAnimationTrigger) {
- // Un-dim the view before/while launching the target
- AnimationProps animation = new AnimationProps(duration, Interpolators.ALPHA_OUT)
- .setListener(postAnimationTrigger.decrementOnAnimationEnd());
+ public void onStartLaunchTargetEnterAnimation(TaskViewTransform transform, int duration,
+ boolean screenPinningEnabled, ReferenceCountedTrigger postAnimationTrigger) {
+ // Dim the view after the app window transitions down into recents
postAnimationTrigger.increment();
- animateDimAlpha(0, animation);
+ AnimationProps animation = new AnimationProps(duration, Interpolators.ALPHA_OUT);
+ Animator anim = animation.apply(AnimationProps.DIM_ALPHA, ObjectAnimator.ofFloat(this,
+ DIM_ALPHA_WITHOUT_HEADER, getDimAlpha(), transform.dimAlpha));
+ anim.addListener(postAnimationTrigger.decrementOnAnimationEnd());
+ anim.start();
if (screenPinningEnabled) {
showActionButton(true /* fadeIn */, duration /* fadeInDuration */);
@@ -540,7 +537,9 @@
ReferenceCountedTrigger postAnimationTrigger) {
// Un-dim the view before/while launching the target
AnimationProps animation = new AnimationProps(duration, Interpolators.ALPHA_OUT);
- animateDimAlpha(0, animation);
+ Animator anim = animation.apply(AnimationProps.DIM_ALPHA, ObjectAnimator.ofFloat(this,
+ DIM_ALPHA, getDimAlpha(), 0));
+ anim.start();
postAnimationTrigger.increment();
hideActionButton(true /* fadeOut */, duration,
@@ -603,7 +602,7 @@
EventBus.getDefault().send(new LaunchTaskEvent(this, mTask, null, INVALID_STACK_ID,
screenPinningRequested));
- MetricsLogger.action(v.getContext(), MetricsEvent.OVERVIEW_SELECT,
+ MetricsLogger.action(v.getContext(), MetricsEvent.ACTION_OVERVIEW_SELECT,
mTask.key.getComponent().toString());
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
index 05a8527..b2a7d90 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
@@ -347,9 +347,11 @@
* Sets the dim alpha, only used when we are not using hardware layers.
* (see RecentsConfiguration.useHardwareLayers)
*/
- void setDimAlpha(float dimAlpha) {
- mDimAlpha = dimAlpha;
- updateBackgroundColor(mBackground.getColor(), dimAlpha);
+ public void setDimAlpha(float dimAlpha) {
+ if (Float.compare(mDimAlpha, dimAlpha) != 0) {
+ mDimAlpha = dimAlpha;
+ updateBackgroundColor(mBackground.getColor(), dimAlpha);
+ }
}
/**
@@ -377,7 +379,9 @@
int primaryColor = disabledInSafeMode
? mDisabledTaskBarBackgroundColor
: t.colorPrimary;
- updateBackgroundColor(primaryColor, mDimAlpha);
+ if (mBackground.getColor() != primaryColor) {
+ updateBackgroundColor(primaryColor, mDimAlpha);
+ }
if (t.icon != null) {
mIconView.setImageDrawable(t.icon);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index 178838e..469a1fc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -194,6 +194,7 @@
// public mode, private notifications, etc
private boolean mLockscreenPublicMode = false;
private final SparseBooleanArray mUsersAllowingPrivateNotifications = new SparseBooleanArray();
+ private final SparseBooleanArray mUsersAllowingNotifications = new SparseBooleanArray();
private UserManager mUserManager;
private int mDensity;
@@ -1089,6 +1090,8 @@
@Override
public void onGearDisplayed(ExpandableNotificationRow row) {
+ MetricsLogger.action(mContext, MetricsEvent.ACTION_REVEAL_GEAR,
+ row.getStatusBarNotification().getPackageName());
mNotificationGearDisplayed = row;
}
@@ -1302,6 +1305,26 @@
}
/**
+ * Has the given user chosen to allow notifications to be shown even when the lockscreen is in
+ * "public" (secure & locked) mode?
+ */
+ public boolean userAllowsNotificationsInPublic(int userHandle) {
+ if (userHandle == UserHandle.USER_ALL) {
+ return true;
+ }
+
+ if (mUsersAllowingNotifications.indexOfKey(userHandle) < 0) {
+ final boolean allowed = 0 != Settings.Secure.getIntForUser(
+ mContext.getContentResolver(),
+ Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS, 0, userHandle);
+ mUsersAllowingNotifications.append(userHandle, allowed);
+ return allowed;
+ }
+
+ return mUsersAllowingNotifications.get(userHandle);
+ }
+
+ /**
* Has the given user chosen to allow their private (full) notifications to be shown even
* when the lockscreen is in "public" (secure & locked) mode?
*/
@@ -1333,13 +1356,30 @@
}
/**
- * Returns true if we're on a secure lockscreen and the user wants to hide "sensitive"
- * notification data. If so, private notifications should show their (possibly
- * auto-generated) publicVersion, and secret notifications should be totally invisible.
+ * Returns true if we're on a secure lockscreen and the user wants to hide notification data.
+ * If so, notifications should be hidden.
*/
@Override // NotificationData.Environment
- public boolean shouldHideSensitiveContents(int userid) {
- return isLockscreenPublicMode() && !userAllowsPrivateNotificationsInPublic(userid);
+ public boolean shouldHideNotifications(int userid) {
+ return isLockscreenPublicMode() && !userAllowsNotificationsInPublic(userid);
+ }
+
+ /**
+ * Returns true if we're on a secure lockscreen and the user wants to hide notifications via
+ * package-specific override.
+ */
+ @Override // NotificationDate.Environment
+ public boolean shouldHideNotifications(String key) {
+ return isLockscreenPublicMode()
+ && mNotificationData.getVisibilityOverride(key) == Notification.VISIBILITY_SECRET;
+ }
+
+ /**
+ * Returns true if we're on a secure lockscreen.
+ */
+ @Override // NotificationData.Environment
+ public boolean onSecureLockScreen() {
+ return isLockscreenPublicMode();
}
public void onNotificationClear(StatusBarNotification notification) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
index f446593..12a83fd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
@@ -105,7 +105,6 @@
private boolean mClearable;
private ExpansionLogger mLogger;
private String mLoggingKey;
- private boolean mWasReset;
private NotificationSettingsIconRow mSettingsIconRow;
private NotificationGuts mGuts;
private NotificationData.Entry mEntry;
@@ -615,20 +614,16 @@
mShowingPublicInitialized = false;
mIsSystemExpanded = false;
mOnKeyguard = false;
- mPublicLayout.reset(mIsHeadsUp);
- mPrivateLayout.reset(mIsHeadsUp);
+ mPublicLayout.reset();
+ mPrivateLayout.reset();
resetHeight();
resetTranslation();
logExpansionEvent(false, wasExpanded);
}
public void resetHeight() {
- if (mIsHeadsUp) {
- resetActualHeight();
- }
mMaxExpandHeight = 0;
mHeadsUpHeight = 0;
- mWasReset = true;
onHeightReset();
requestLayout();
}
@@ -684,7 +679,7 @@
mTranslateableViews.remove(mGutsStub);
}
- public void setTranslationForOutline(float translationX) {
+ private void setTranslationForOutline(float translationX) {
setOutlineRect(false, translationX, getTop(), getRight() + translationX, getBottom());
}
@@ -704,6 +699,46 @@
if (mTranslateAnim != null) {
mTranslateAnim.cancel();
}
+ mTranslateAnim = (AnimatorSet) getTranslateViewAnimator(leftTarget,
+ null /* updateListener */);
+ if (mTranslateAnim != null) {
+ mTranslateAnim.start();
+ }
+ }
+
+ @Override
+ public void setTranslation(float translationX) {
+ if (areGutsExposed()) {
+ // Don't translate if guts are showing.
+ return;
+ }
+ // Translate the group of views
+ for (int i = 0; i < mTranslateableViews.size(); i++) {
+ if (mTranslateableViews.get(i) != null) {
+ mTranslateableViews.get(i).setTranslationX(translationX);
+ }
+ }
+ setTranslationForOutline(translationX);
+ if (mSettingsIconRow != null) {
+ mSettingsIconRow.updateSettingsIcons(translationX, getMeasuredWidth());
+ }
+ }
+
+ @Override
+ public float getTranslation() {
+ if (mTranslateableViews != null && mTranslateableViews.size() > 0) {
+ // All of the views in the list should have same translation, just use first one.
+ return mTranslateableViews.get(0).getTranslationX();
+ }
+ return 0;
+ }
+
+ public Animator getTranslateViewAnimator(final float leftTarget,
+ AnimatorUpdateListener listener) {
+ if (areGutsExposed()) {
+ // No translation if guts are exposed.
+ return null;
+ }
AnimatorSet set = new AnimatorSet();
if (mTranslateableViews != null) {
for (int i = 0; i < mTranslateableViews.size(); i++) {
@@ -715,8 +750,15 @@
@Override
public void onAnimationUpdate(ValueAnimator animation) {
setTranslationForOutline((float) animation.getAnimatedValue());
+ if (mSettingsIconRow != null) {
+ mSettingsIconRow.updateSettingsIcons(
+ (float) animation.getAnimatedValue(), getMeasuredWidth());
+ }
}
});
+ if (listener != null) {
+ translateAnim.addUpdateListener(listener);
+ }
}
translateAnim.addListener(new AnimatorListenerAdapter() {
@Override
@@ -730,8 +772,7 @@
set.play(translateAnim);
}
}
- mTranslateAnim = set;
- set.start();
+ return set;
}
public float getSpaceForGear() {
@@ -748,10 +789,6 @@
return mSettingsIconRow;
}
- public ArrayList<View> getContentViews() {
- return mTranslateableViews;
- }
-
public void inflateGuts() {
if (mGuts == null) {
mGutsStub.inflate();
@@ -922,18 +959,6 @@
return mStatusBarNotification != null && mStatusBarNotification.isClearable();
}
- /**
- * Apply an expansion state to the layout.
- */
- public void applyExpansionToLayout() {
- boolean expand = isExpanded();
- if (expand && mExpandable) {
- setActualHeight(mMaxExpandHeight);
- } else {
- setActualHeight(getMinHeight());
- }
- }
-
@Override
public int getIntrinsicHeight() {
if (isUserLocked()) {
@@ -1015,12 +1040,7 @@
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
- boolean updateExpandHeight = mMaxExpandHeight == 0 && !mWasReset;
updateMaxHeights();
- if (updateExpandHeight) {
- applyExpansionToLayout();
- }
- mWasReset = false;
}
private void updateMaxHeights() {
@@ -1169,6 +1189,10 @@
return mMaxExpandHeight;
}
+ public boolean areGutsExposed() {
+ return (mGuts != null && mGuts.areGutsExposed());
+ }
+
@Override
public boolean isContentExpandable() {
NotificationContentView showingLayout = getShowingLayout();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
index 1ff87f5..c0e4340 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
@@ -36,7 +36,6 @@
protected OnHeightChangedListener mOnHeightChangedListener;
private int mActualHeight;
protected int mClipTopAmount;
- private boolean mActualHeightInitialized;
private boolean mDark;
private ArrayList<View> mMatchParentViews = new ArrayList<View>();
private int mClipTopOptimization;
@@ -99,28 +98,9 @@
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
- if (!mActualHeightInitialized && mActualHeight == 0) {
- int initialHeight = getInitialHeight();
- if (initialHeight != 0) {
- setActualHeight(initialHeight);
- }
- }
updateClipping();
}
- /**
- * Resets the height of the view on the next layout pass
- */
- protected void resetActualHeight() {
- mActualHeight = 0;
- mActualHeightInitialized = false;
- requestLayout();
- }
-
- protected int getInitialHeight() {
- return getHeight();
- }
-
@Override
public boolean pointInView(float localX, float localY, float slop) {
float top = mClipTopAmount;
@@ -137,7 +117,6 @@
* @param notifyListeners Whether the listener should be informed about the change.
*/
public void setActualHeight(int actualHeight, boolean notifyListeners) {
- mActualHeightInitialized = true;
mActualHeight = actualHeight;
updateClipping();
if (notifyListeners) {
@@ -283,6 +262,20 @@
public void setBelowSpeedBump(boolean below) {
}
+ /**
+ * Sets the translation of the view.
+ */
+ public void setTranslation(float translation) {
+ setTranslationX(translation);
+ }
+
+ /**
+ * Gets the translation of the view.
+ */
+ public float getTranslation() {
+ return getTranslationX();
+ }
+
public void onHeightReset() {
if (mOnHeightChangedListener != null) {
mOnHeightChangedListener.onReset(this);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
index 7c11161..b94c15b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
@@ -92,7 +92,14 @@
= new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
- mAnimate = true;
+ // We need to post since we don't want the notification to animate on the very first
+ // frame
+ post(new Runnable() {
+ @Override
+ public void run() {
+ mAnimate = true;
+ }
+ });
getViewTreeObserver().removeOnPreDrawListener(this);
return true;
}
@@ -113,7 +120,7 @@
R.dimen.min_notification_layout_height);
mNotificationContentMarginEnd = getResources().getDimensionPixelSize(
com.android.internal.R.dimen.notification_content_margin_end);
- reset(true);
+ reset();
}
public void setHeights(int smallHeight, int headsUpMaxHeight, int maxHeight) {
@@ -248,7 +255,7 @@
updateVisibility();
}
- public void reset(boolean resetActualHeight) {
+ public void reset() {
if (mContractedChild != null) {
mContractedChild.animate().cancel();
removeView(mContractedChild);
@@ -264,10 +271,6 @@
mContractedChild = null;
mExpandedChild = null;
mHeadsUpChild = null;
- mVisibleType = VISIBLE_TYPE_CONTRACTED;
- if (resetActualHeight) {
- mContentHeight = mSmallHeight;
- }
}
public View getContractedChild() {
@@ -477,12 +480,18 @@
private void animateToVisibleType(int visibleType) {
final TransformableView shownView = getTransformableViewForVisibleType(visibleType);
final TransformableView hiddenView = getTransformableViewForVisibleType(mVisibleType);
+ if (shownView == hiddenView) {
+ shownView.setVisible(true);
+ return;
+ }
shownView.transformFrom(hiddenView);
getViewForVisibleType(visibleType).setVisibility(View.VISIBLE);
hiddenView.transformTo(shownView, new Runnable() {
@Override
public void run() {
- hiddenView.setVisible(false);
+ if (hiddenView != getTransformableViewForVisibleType(mVisibleType)) {
+ hiddenView.setVisible(false);
+ }
}
});
}
@@ -543,6 +552,9 @@
|| mContainingNotification.isExpanded()
? mContainingNotification.getMaxContentHeight()
: mContainingNotification.getShowingLayout().getMinHeight();
+ if (height == 0) {
+ height = mContentHeight;
+ }
int expandedVisualType = getVisualTypeForHeight(height);
int collapsedVisualType = getVisualTypeForHeight(
mContainingNotification.getMinExpandHeight());
@@ -550,7 +562,12 @@
? expandedVisualType
: collapsedVisualType;
}
- int viewHeight = Math.min(mContentHeight, mContainingNotification.getIntrinsicHeight());
+ int intrinsicHeight = mContainingNotification.getIntrinsicHeight();
+ int viewHeight = mContentHeight;
+ if (intrinsicHeight != 0) {
+ // the intrinsicHeight might be 0 because it was just reset.
+ viewHeight = Math.min(mContentHeight, intrinsicHeight);
+ }
return getVisualTypeForHeight(viewHeight);
}
@@ -631,7 +648,6 @@
mBeforeN = entry.targetSdk < Build.VERSION_CODES.N;
updateSingleLineView();
applyRemoteInput(entry);
- selectLayout(false /* animate */, true /* force */);
if (mContractedChild != null) {
mContractedWrapper.notifyContentUpdated(entry.notification);
}
@@ -641,6 +657,7 @@
if (mHeadsUpChild != null) {
mHeadsUpWrapper.notifyContentUpdated(entry.notification);
}
+ selectLayout(false /* animate */, true /* force */);
setDark(mDark, false /* animate */, 0 /* delay */);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
index 7cb9127..c9fe2bd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
@@ -353,8 +353,10 @@
return true;
}
- if (sbn.getNotification().visibility == Notification.VISIBILITY_SECRET &&
- mEnvironment.shouldHideSensitiveContents(sbn.getUserId())) {
+ if (mEnvironment.onSecureLockScreen() &&
+ (sbn.getNotification().visibility == Notification.VISIBILITY_SECRET
+ || mEnvironment.shouldHideNotifications(sbn.getUserId())
+ || mEnvironment.shouldHideNotifications(sbn.getKey()))) {
return true;
}
@@ -433,7 +435,9 @@
* Provides access to keyguard state and user settings dependent data.
*/
public interface Environment {
- public boolean shouldHideSensitiveContents(int userid);
+ public boolean onSecureLockScreen();
+ public boolean shouldHideNotifications(int userid);
+ public boolean shouldHideNotifications(String key);
public boolean isDeviceProvisioned();
public boolean isNotificationForCurrentProfiles(StatusBarNotification sbn);
public String getCurrentMediaNotificationKey();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java
index 1c16bdc..45a24a0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java
@@ -130,7 +130,12 @@
importanceSlider.setVisibility(View.VISIBLE);
importanceButtons.setVisibility(View.GONE);
} else {
- bindToggles(importanceButtons, sbn, systemApp);
+ int userImportance = NotificationListenerService.Ranking.IMPORTANCE_UNSPECIFIED;
+ try {
+ userImportance =
+ mINotificationManager.getImportance(sbn.getPackageName(), sbn.getUid());
+ } catch (RemoteException e) {}
+ bindToggles(importanceButtons, userImportance, systemApp);
importanceButtons.setVisibility(View.VISIBLE);
importanceSlider.setVisibility(View.GONE);
}
@@ -144,7 +149,7 @@
if (mBlock.isChecked()) {
progress = NotificationListenerService.Ranking.IMPORTANCE_NONE;
} else if (mSilent.isChecked()) {
- progress = NotificationListenerService.Ranking.IMPORTANCE_DEFAULT;
+ progress = NotificationListenerService.Ranking.IMPORTANCE_LOW;
} else {
progress = NotificationListenerService.Ranking.IMPORTANCE_UNSPECIFIED;
}
@@ -158,7 +163,7 @@
}
}
- private void bindToggles(final View importanceButtons, final StatusBarNotification sbn,
+ private void bindToggles(final View importanceButtons, final int importance,
final boolean systemApp) {
mBlock = (RadioButton) importanceButtons.findViewById(R.id.block_importance);
mSilent = (RadioButton) importanceButtons.findViewById(R.id.silent_importance);
@@ -169,7 +174,11 @@
} else {
mReset.setText(mContext.getString(R.string.do_not_silence_block));
}
- mReset.setChecked(true);
+ if (importance == NotificationListenerService.Ranking.IMPORTANCE_LOW) {
+ mSilent.setChecked(true);
+ } else {
+ mReset.setChecked(true);
+ }
}
private void bindSlider(final View importanceSlider, final StatusBarNotification sbn,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
index 960e4cf..988d537 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
@@ -221,6 +221,7 @@
apply();
applyIconTint();
+ mNC.addSignalCallback(this);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ViewTransformationHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/ViewTransformationHelper.java
index bf05d1d..66f945e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ViewTransformationHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ViewTransformationHelper.java
@@ -76,26 +76,26 @@
});
mViewTransformationAnimation.setInterpolator(Interpolators.LINEAR);
mViewTransformationAnimation.setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD);
- if (endRunnable != null) {
- mViewTransformationAnimation.addListener(new AnimatorListenerAdapter() {
- public boolean mCancelled;
+ mViewTransformationAnimation.addListener(new AnimatorListenerAdapter() {
+ public boolean mCancelled;
- @Override
- public void onAnimationEnd(Animator animation) {
- endRunnable.run();
- if (!mCancelled) {
- setVisible(false);
- } else {
- abortTransformations();
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ if (!mCancelled) {
+ if (endRunnable != null) {
+ endRunnable.run();
}
+ setVisible(false);
+ } else {
+ abortTransformations();
}
+ }
- @Override
- public void onAnimationCancel(Animator animation) {
- mCancelled = true;
- }
- });
- }
+ @Override
+ public void onAnimationCancel(Animator animation) {
+ mCancelled = true;
+ }
+ });
mViewTransformationAnimation.start();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/TextViewTransformState.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/TextViewTransformState.java
index 5ab441d..d3393b3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/TextViewTransformState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/TextViewTransformState.java
@@ -16,6 +16,7 @@
package com.android.systemui.statusbar.notification;
+import android.text.Layout;
import android.text.TextUtils;
import android.util.Pools;
import android.view.View;
@@ -28,14 +29,13 @@
private static Pools.SimplePool<TextViewTransformState> sInstancePool
= new Pools.SimplePool<>(40);
- private CharSequence mText;
+ private TextView mText;
@Override
public void initFrom(View view) {
super.initFrom(view);
if (view instanceof TextView) {
- TextView txt = (TextView) view;
- mText = txt.getText();
+ mText = (TextView) view;
}
}
@@ -43,11 +43,27 @@
protected boolean sameAs(TransformState otherState) {
if (otherState instanceof TextViewTransformState) {
TextViewTransformState otherTvs = (TextViewTransformState) otherState;
- return TextUtils.equals(otherTvs.mText, mText);
+ if(TextUtils.equals(otherTvs.mText.getText(), mText.getText())) {
+ int ownEllipsized = getEllipsisCount();
+ int otherEllipsized = otherTvs.getEllipsisCount();
+ return ownEllipsized == otherEllipsized;
+ }
}
return super.sameAs(otherState);
}
+ private int getEllipsisCount() {
+ Layout l = mText.getLayout();
+ if (l != null) {
+ int lines = l.getLineCount();
+ if (lines > 0) {
+ // we only care about the first line
+ return l.getEllipsisCount(0);
+ }
+ }
+ return 0;
+ }
+
public static TextViewTransformState obtain() {
TextViewTransformState instance = sInstancePool.acquire();
if (instance != null) {
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 127feba..88b8afa 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -1397,7 +1397,7 @@
// In Shade, interpolate linearly such that QS is closed whenever panel height is
// minimum QS expansion + minStackHeight
float panelHeightQsCollapsed = mNotificationStackScroller.getIntrinsicPadding()
- + mNotificationStackScroller.getMinStackHeight();
+ + mNotificationStackScroller.getLayoutMinHeight();
float panelHeightQsExpanded = calculatePanelHeightQsExpanded();
t = (expandedHeight - panelHeightQsCollapsed)
/ (panelHeightQsExpanded - panelHeightQsCollapsed);
@@ -1453,7 +1453,7 @@
&& mShadeEmpty) {
notificationHeight = mNotificationStackScroller.getEmptyShadeViewHeight()
+ mNotificationStackScroller.getBottomStackPeekSize()
- + mNotificationStackScroller.getCollapseSecondCardPadding();
+ + mNotificationStackScroller.getBottomStackSlowDownHeight();
}
int maxQsHeight = mQsMaxExpansionHeight;
@@ -1468,7 +1468,7 @@
+ notificationHeight;
if (totalHeight > mNotificationStackScroller.getHeight()) {
float fullyCollapsedHeight = maxQsHeight
- + mNotificationStackScroller.getMinStackHeight();
+ + mNotificationStackScroller.getLayoutMinHeight();
totalHeight = Math.max(fullyCollapsedHeight, mNotificationStackScroller.getHeight());
}
return (int) totalHeight;
@@ -1485,7 +1485,7 @@
private float getFadeoutAlpha() {
float alpha = (getNotificationsTopY() + mNotificationStackScroller.getFirstItemMinHeight())
/ (mQsMinExpansionHeight + mNotificationStackScroller.getBottomStackPeekSize()
- - mNotificationStackScroller.getCollapseSecondCardPadding());
+ - mNotificationStackScroller.getBottomStackSlowDownHeight());
alpha = Math.max(0, Math.min(alpha, 1));
alpha = (float) Math.pow(alpha, 0.75);
return alpha;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index e739944..ef16388 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -995,7 +995,6 @@
SignalClusterView signalCluster =
(SignalClusterView) containerView.findViewById(R.id.signal_cluster);
if (signalCluster != null) {
- mNetworkController.addSignalCallback(signalCluster);
signalCluster.setSecurityController(mSecurityController);
signalCluster.setNetworkController(mNetworkController);
}
@@ -1597,8 +1596,7 @@
}
private boolean packageHasVisibilityOverride(String key) {
- return mNotificationData.getVisibilityOverride(key)
- != NotificationListenerService.Ranking.VISIBILITY_NO_OVERRIDE;
+ return mNotificationData.getVisibilityOverride(key) == Notification.VISIBILITY_PRIVATE;
}
private void updateClearAll() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/EthernetSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/EthernetSignalController.java
index bd36462..159bd41 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/EthernetSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/EthernetSignalController.java
@@ -19,6 +19,7 @@
import android.net.NetworkCapabilities;
import com.android.systemui.statusbar.policy.NetworkController.IconState;
+import com.android.systemui.statusbar.policy.NetworkController.SignalCallback;
import java.util.BitSet;
@@ -46,12 +47,12 @@
}
@Override
- public void notifyListeners() {
+ public void notifyListeners(SignalCallback callback) {
boolean ethernetVisible = mCurrentState.connected;
String contentDescription = getStringIfExists(getContentDescription());
// TODO: wire up data transfer using WifiSignalPoller.
- mCallbackHandler.setEthernetIndicators(new IconState(ethernetVisible, getCurrentIconId(),
+ callback.setEthernetIndicators(new IconState(ethernetVisible, getCurrentIconId(),
contentDescription));
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
index 8fd4d9c..80dcfb6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
@@ -34,6 +34,7 @@
import com.android.internal.telephony.cdma.EriInfo;
import com.android.systemui.R;
import com.android.systemui.statusbar.policy.NetworkController.IconState;
+import com.android.systemui.statusbar.policy.NetworkController.SignalCallback;
import com.android.systemui.statusbar.policy.NetworkControllerImpl.Config;
import com.android.systemui.statusbar.policy.NetworkControllerImpl.SubscriptionDefaults;
@@ -198,7 +199,7 @@
}
@Override
- public void notifyListeners() {
+ public void notifyListeners(SignalCallback callback) {
MobileIconGroup icons = getIcons();
String contentDescription = getStringIfExists(getContentDescription());
@@ -231,7 +232,7 @@
|| mCurrentState.iconGroup == TelephonyIcons.ROAMING
|| mCurrentState.iconGroup == TelephonyIcons.DATA_DISABLED;
int typeIcon = showDataIcon ? icons.mDataType : 0;
- mCallbackHandler.setMobileDataIndicators(statusIcon, qsIcon, typeIcon, qsTypeIcon,
+ callback.setMobileDataIndicators(statusIcon, qsIcon, typeIcon, qsTypeIcon,
activityIn, activityOut, dataContentDescription, description, icons.mIsWide,
mSubscriptionInfo.getSubscriptionId());
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
index 8193b52..40eb71d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
@@ -322,16 +322,16 @@
}
public void addSignalCallback(SignalCallback cb) {
- mCallbackHandler.setListening(cb, true);
- mCallbackHandler.setSubs(mCurrentSubscriptions);
- mCallbackHandler.setIsAirplaneMode(new IconState(mAirplaneMode,
+ cb.setSubs(mCurrentSubscriptions);
+ cb.setIsAirplaneMode(new IconState(mAirplaneMode,
TelephonyIcons.FLIGHT_MODE_ICON, R.string.accessibility_airplane_mode, mContext));
- mCallbackHandler.setNoSims(mHasNoSims);
- mWifiSignalController.notifyListeners();
- mEthernetSignalController.notifyListeners();
+ cb.setNoSims(mHasNoSims);
+ mWifiSignalController.notifyListeners(cb);
+ mEthernetSignalController.notifyListeners(cb);
for (MobileSignalController mobileSignalController : mMobileSignalControllers.values()) {
- mobileSignalController.notifyListeners();
+ mobileSignalController.notifyListeners(cb);
}
+ mCallbackHandler.setListening(cb, true);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SignalController.java
index c954d08..4cfd1c7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SignalController.java
@@ -18,6 +18,7 @@
import android.content.Context;
import android.text.format.DateFormat;
import android.util.Log;
+import com.android.systemui.statusbar.policy.NetworkController.SignalCallback;
import java.io.PrintWriter;
import java.util.BitSet;
@@ -48,7 +49,7 @@
// is aware of current state.
protected final NetworkControllerImpl mNetworkController;
- protected final CallbackHandler mCallbackHandler;
+ private final CallbackHandler mCallbackHandler;
// Save the previous HISTORY_SIZE states for logging.
private final State[] mHistory;
@@ -198,12 +199,16 @@
}
}
+ public final void notifyListeners() {
+ notifyListeners(mCallbackHandler);
+ }
+
/**
* Trigger callbacks based on current state. The callbacks should be completely
* based on current state, and only need to be called in the scenario where
* mCurrentState != mLastState.
*/
- public abstract void notifyListeners();
+ public abstract void notifyListeners(SignalCallback callback);
/**
* Generate a blank T.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
index 53fd446..cedc3c7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
@@ -37,6 +37,8 @@
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
+import android.telephony.PhoneStateListener;
+import android.telephony.TelephonyManager;
import android.util.Log;
import android.util.SparseArray;
import android.util.SparseBooleanArray;
@@ -99,7 +101,6 @@
private boolean mSimpleUserSwitcher;
private boolean mAddUsersWhenLocked;
private boolean mPauseRefreshUsers;
- private boolean mAllowUserSwitchingWhenSystemUserLocked;
private SparseBooleanArray mForcePictureLoadForUserId = new SparseBooleanArray(2);
public UserSwitcherController(Context context, KeyguardMonitor keyguardMonitor,
@@ -140,6 +141,7 @@
mSettingsObserver.onChange(false);
keyguardMonitor.addCallback(mCallback);
+ listenForCallState();
refreshUsers(UserHandle.USER_NULL);
}
@@ -186,8 +188,7 @@
}
ArrayList<UserRecord> records = new ArrayList<>(infos.size());
int currentId = ActivityManager.getCurrentUser();
- boolean allowUserSwitching = mAllowUserSwitchingWhenSystemUserLocked
- || mUserManager.isUserUnlocked(UserHandle.SYSTEM);
+ boolean canSwitchUsers = mUserManager.canSwitchUsers();
UserInfo currentUserInfo = null;
UserRecord guestRecord = null;
int avatarSize = mContext.getResources()
@@ -198,12 +199,14 @@
if (isCurrent) {
currentUserInfo = info;
}
- boolean switchToEnabled = allowUserSwitching || isCurrent;
+ boolean switchToEnabled = canSwitchUsers || isCurrent;
if (info.isEnabled()) {
if (info.isGuest()) {
+ // Tapping guest icon triggers remove and a user switch therefore
+ // the icon shouldn't be enabled even if the user is current
guestRecord = new UserRecord(info, null /* picture */,
true /* isGuest */, isCurrent, false /* isAddUser */,
- false /* isRestricted */, switchToEnabled);
+ false /* isRestricted */, canSwitchUsers);
} else if (info.supportsSwitchToByUser()) {
Bitmap picture = bitmaps.get(info.id);
if (picture == null) {
@@ -240,7 +243,7 @@
if (canCreateGuest) {
guestRecord = new UserRecord(null /* info */, null /* picture */,
true /* isGuest */, false /* isCurrent */,
- false /* isAddUser */, createIsRestricted, allowUserSwitching);
+ false /* isAddUser */, createIsRestricted, canSwitchUsers);
checkIfAddUserDisallowedByAdminOnly(guestRecord);
records.add(guestRecord);
}
@@ -253,7 +256,7 @@
if (!mSimpleUserSwitcher && canCreateUser) {
UserRecord addUserRecord = new UserRecord(null /* info */, null /* picture */,
false /* isGuest */, false /* isCurrent */, true /* isAddUser */,
- createIsRestricted, allowUserSwitching);
+ createIsRestricted, canSwitchUsers);
checkIfAddUserDisallowedByAdminOnly(addUserRecord);
records.add(addUserRecord);
}
@@ -417,6 +420,24 @@
mUserManager.removeUser(id);
}
+ private void listenForCallState() {
+ TelephonyManager.from(mContext).listen(new PhoneStateListener() {
+ private int mCallState;
+ @Override
+ public void onCallStateChanged(int state, String incomingNumber) {
+ if (mCallState == state) return;
+ if (DEBUG) Log.v(TAG, "Call state changed: " + state);
+ mCallState = state;
+ int currentUserId = ActivityManager.getCurrentUser();
+ UserInfo userInfo = mUserManager.getUserInfo(currentUserId);
+ if (userInfo != null && userInfo.isGuest()) {
+ showGuestNotification(currentUserId);
+ }
+ refreshUsers(UserHandle.USER_NULL);
+ }
+ }, PhoneStateListener.LISTEN_CALL_STATE);
+ }
+
private BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
@@ -488,25 +509,6 @@
}
}
- private void showGuestNotification(int guestUserId) {
- PendingIntent removeGuestPI = PendingIntent.getBroadcastAsUser(mContext,
- 0, new Intent(ACTION_REMOVE_GUEST), 0, UserHandle.SYSTEM);
- Notification notification = new Notification.Builder(mContext)
- .setVisibility(Notification.VISIBILITY_SECRET)
- .setPriority(Notification.PRIORITY_MIN)
- .setSmallIcon(R.drawable.ic_person)
- .setContentTitle(mContext.getString(R.string.guest_notification_title))
- .setContentText(mContext.getString(R.string.guest_notification_text))
- .setContentIntent(removeGuestPI)
- .setShowWhen(false)
- .addAction(R.drawable.ic_delete,
- mContext.getString(R.string.guest_notification_remove_action),
- removeGuestPI)
- .build();
- NotificationManager.from(mContext).notifyAsUser(TAG_REMOVE_GUEST, ID_REMOVE_GUEST,
- notification, new UserHandle(guestUserId));
- }
-
private void showLogoutNotification(int userId) {
PendingIntent logoutPI = PendingIntent.getBroadcastAsUser(mContext,
0, new Intent(ACTION_LOGOUT_USER), 0, UserHandle.SYSTEM);
@@ -528,6 +530,28 @@
}
};
+ private void showGuestNotification(int guestUserId) {
+ boolean canSwitchUsers = mUserManager.canSwitchUsers();
+ // Disable 'Remove guest' action if cannot switch users right now
+ PendingIntent removeGuestPI = canSwitchUsers ? PendingIntent.getBroadcastAsUser(mContext,
+ 0, new Intent(ACTION_REMOVE_GUEST), 0, UserHandle.SYSTEM) : null;
+
+ Notification notification = new Notification.Builder(mContext)
+ .setVisibility(Notification.VISIBILITY_SECRET)
+ .setPriority(Notification.PRIORITY_MIN)
+ .setSmallIcon(R.drawable.ic_person)
+ .setContentTitle(mContext.getString(R.string.guest_notification_title))
+ .setContentText(mContext.getString(R.string.guest_notification_text))
+ .setContentIntent(removeGuestPI)
+ .setShowWhen(false)
+ .addAction(R.drawable.ic_delete,
+ mContext.getString(R.string.guest_notification_remove_action),
+ removeGuestPI)
+ .build();
+ NotificationManager.from(mContext).notifyAsUser(TAG_REMOVE_GUEST, ID_REMOVE_GUEST,
+ notification, new UserHandle(guestUserId));
+ }
+
private final Runnable mUnpauseRefreshUsers = new Runnable() {
@Override
public void run() {
@@ -543,9 +567,6 @@
SIMPLE_USER_SWITCHER_GLOBAL_SETTING, 0) != 0;
mAddUsersWhenLocked = Settings.Global.getInt(mContext.getContentResolver(),
Settings.Global.ADD_USERS_WHEN_LOCKED, 0) != 0;
- mAllowUserSwitchingWhenSystemUserLocked = Settings.Global.getInt(
- mContext.getContentResolver(),
- Settings.Global.ALLOW_USER_SWITCHING_WHEN_SYSTEM_USER_LOCKED, 0) != 0;
refreshUsers(UserHandle.USER_NULL);
};
};
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java
index cc98eb6..a6ed04f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java
@@ -28,6 +28,7 @@
import com.android.internal.util.AsyncChannel;
import com.android.settingslib.wifi.WifiStatusTracker;
import com.android.systemui.statusbar.policy.NetworkController.IconState;
+import com.android.systemui.statusbar.policy.NetworkController.SignalCallback;
import java.util.Objects;
@@ -72,7 +73,7 @@
}
@Override
- public void notifyListeners() {
+ public void notifyListeners(SignalCallback callback) {
// only show wifi in the cluster if connected or if wifi-only
boolean wifiVisible = mCurrentState.enabled
&& (mCurrentState.connected || !mHasMobileData);
@@ -83,7 +84,7 @@
IconState statusIcon = new IconState(wifiVisible, getCurrentIconId(), contentDescription);
IconState qsIcon = new IconState(mCurrentState.connected, getQsCurrentIconId(),
contentDescription);
- mCallbackHandler.setWifiIndicators(mCurrentState.enabled, statusIcon, qsIcon,
+ callback.setWifiIndicators(mCurrentState.enabled, statusIcon, qsIcon,
ssidPresent && mCurrentState.activityIn, ssidPresent && mCurrentState.activityOut,
wifiDesc);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
index 85b1426..aa444f5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -48,6 +48,8 @@
import android.view.animation.Interpolator;
import android.widget.OverScroller;
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.MetricsProto.MetricsEvent;
import com.android.systemui.ExpandHelper;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
@@ -363,6 +365,8 @@
@Override
public void onGearTouched(ExpandableNotificationRow row, int x, int y) {
if (mLongPressListener != null) {
+ MetricsLogger.action(mContext, MetricsEvent.ACTION_TOUCH_GEAR,
+ row.getStatusBarNotification().getPackageName());
mLongPressListener.onLongPress(row, x, y);
}
}
@@ -418,12 +422,9 @@
.getDimensionPixelSize(R.dimen.notification_divider_height));
mIncreasedPaddingBetweenElements = context.getResources()
.getDimensionPixelSize(R.dimen.notification_divider_height_increased);
-
mBottomStackSlowDownHeight = mStackScrollAlgorithm.getBottomStackSlowDownLength();
mMinTopOverScrollToEscape = getResources().getDimensionPixelSize(
R.dimen.min_top_overscroll_to_qs);
- mCollapseSecondCardPadding = getResources().getDimensionPixelSize(
- R.dimen.notification_collapse_second_card_padding);
}
private void notifyHeightChangeListener(ExpandableView view) {
@@ -509,14 +510,6 @@
}
/**
- * @return whether the height of the layout needs to be adapted, in order to ensure that the
- * last child is not in the bottom stack.
- */
- private boolean needsHeightAdaption() {
- return getNotGoneChildCount() > 1;
- }
-
- /**
* Updates the children views according to the stack scroll algorithm. Call this whenever
* modifications to {@link #mOwnScrollY} are performed to reflect it in the view layout.
*/
@@ -599,7 +592,7 @@
mLastSetStackHeight = height;
setIsExpanded(height > 0.0f);
int newStackHeight = (int) height;
- int minStackHeight = getMinStackHeight();
+ int minStackHeight = getLayoutMinHeight();
int stackHeight;
float paddingOffset;
boolean trackingHeadsUp = mTrackingHeadsUp || mHeadsUpManager.hasPinnedHeadsUp();
@@ -612,20 +605,7 @@
stackHeight = newStackHeight;
} else {
int translationY;
- if (!trackingHeadsUp) {
- // We did not reach the position yet where we actually start growing,
- // so we translate the stack upwards.
- translationY = (newStackHeight - minStackHeight);
- // A slight parallax effect is introduced in order for the stack to catch up with
- // the top card.
- float partiallyThere = (newStackHeight - mTopPadding - mTopPaddingOverflow)
- / minStackHeight;
- partiallyThere = Math.max(0, partiallyThere);
- translationY += (1 - partiallyThere) * (mBottomStackPeekSize +
- mCollapseSecondCardPadding);
- } else {
- translationY = (int) (height - normalUnfoldPositionStart);
- }
+ translationY = newStackHeight - normalUnfoldPositionStart;
paddingOffset = translationY - mTopPadding;
stackHeight = (int) (height - (translationY - mTopPadding));
}
@@ -668,8 +648,8 @@
return mBottomStackPeekSize;
}
- public int getCollapseSecondCardPadding() {
- return mCollapseSecondCardPadding;
+ public int getBottomStackSlowDownHeight() {
+ return mBottomStackSlowDownHeight;
}
public void setLongPressListener(SwipeHelper.LongPressListener listener) {
@@ -734,6 +714,7 @@
if (targetLeft == 0 && mCurrIconRow != null) {
mCurrIconRow.resetState();
+ mCurrIconRow = null;
if (mGearExposedView != null && mGearExposedView == mTranslatingParentView) {
mGearExposedView = null;
}
@@ -1850,7 +1831,7 @@
boolean ignoreIntrinsicPadding) {
float start = qsHeight;
float stackHeight = getHeight() - start;
- int minStackHeight = getMinStackHeight();
+ int minStackHeight = getLayoutMinHeight();
if (stackHeight <= minStackHeight) {
float overflow = minStackHeight - stackHeight;
stackHeight = minStackHeight;
@@ -1864,11 +1845,16 @@
setStackHeight(mLastSetStackHeight);
}
- public int getMinStackHeight() {
+ public int getLayoutMinHeight() {
final ExpandableView firstChild = getFirstChildNotGone();
- final int firstChildMinHeight = firstChild != null ? firstChild.getMinHeight()
+ int firstChildMinHeight = firstChild != null
+ ? firstChild.getIntrinsicHeight()
: mCollapsedSize;
- return firstChildMinHeight + mBottomStackPeekSize + mCollapseSecondCardPadding;
+ if (mOwnScrollY > 0) {
+ firstChildMinHeight = Math.max(firstChildMinHeight - mOwnScrollY, mCollapsedSize);
+ }
+ return Math.min(firstChildMinHeight + mBottomStackPeekSize + mBottomStackSlowDownHeight,
+ mMaxLayoutHeight - mTopPadding);
}
public float getTopPaddingOverflow() {
@@ -1880,7 +1866,7 @@
final int firstChildMinHeight = firstChild != null ? (int) firstChild.getMinHeight()
: mCollapsedSize;
return mIntrinsicPadding + firstChildMinHeight + mBottomStackPeekSize
- + mCollapseSecondCardPadding;
+ + mBottomStackSlowDownHeight;
}
private int clampPadding(int desiredPadding) {
@@ -1994,7 +1980,6 @@
}
private void onViewRemovedInternal(View child) {
- mStackScrollAlgorithm.notifyChildrenChanged(this);
if (mChangePositionInProgress) {
// This is only a position change, don't do anything special
return;
@@ -2175,7 +2160,6 @@
private void onViewAddedInternal(View child) {
updateHideSensitiveForChild(child);
- mStackScrollAlgorithm.notifyChildrenChanged(this);
((ExpandableView) child).setOnHeightChangedListener(this);
generateAddAnimation(child, false /* fromMoreCard */);
updateAnimationState(child);
@@ -2643,12 +2627,8 @@
}
public int getEmptyBottomMargin() {
- int emptyMargin = mMaxLayoutHeight - mContentHeight - mBottomStackPeekSize;
- if (needsHeightAdaption()) {
- emptyMargin -= mBottomStackSlowDownHeight;
- } else {
- emptyMargin -= mCollapseSecondCardPadding;
- }
+ int emptyMargin = mMaxLayoutHeight - mContentHeight - mBottomStackPeekSize
+ - mBottomStackSlowDownHeight;
return Math.max(emptyMargin, 0);
}
@@ -2659,12 +2639,10 @@
public void onExpansionStarted() {
mIsExpansionChanging = true;
- mStackScrollAlgorithm.onExpansionStarted(mCurrentStackScrollState);
}
public void onExpansionStopped() {
mIsExpansionChanging = false;
- mStackScrollAlgorithm.onExpansionStopped();
if (!mIsExpanded) {
mOwnScrollY = 0;
@@ -2732,7 +2710,6 @@
if (mIsExpanded && mAnimationsEnabled) {
mRequestViewResizeAnimationOnLayout = true;
}
- mStackScrollAlgorithm.onReset(view);
updateAnimationState(view);
updateChronometerForChild(view);
}
@@ -3163,15 +3140,7 @@
}
public int getDismissViewHeight() {
- int height = mDismissView.getHeight() + mPaddingBetweenElements;
-
- // Hack: Accommodate for additional distance when we only have one notification and the
- // dismiss all button.
- if (getNotGoneChildCount() == 2 && getLastChildNotGone() == mDismissView
- && getFirstChildNotGone() instanceof ActivatableNotificationView) {
- height += mCollapseSecondCardPadding;
- }
- return height;
+ return mDismissView.getHeight() + mPaddingBetweenElements;
}
public int getEmptyShadeViewHeight() {
@@ -3399,7 +3368,6 @@
private static final long GEAR_SHOW_DELAY = 60;
- private ArrayList<View> mTranslatingViews = new ArrayList<>();
private CheckForDrag mCheckForDrag;
private Handler mHandler;
private int mMoveState = MOVE_STATE_UNDEFINED;
@@ -3416,6 +3384,7 @@
// Reset check for drag gesture
mCheckForDrag = null;
+ mCurrIconRow = null;
// Slide back any notifications that might be showing a gear
resetExposedGearView();
@@ -3424,9 +3393,6 @@
// Set the listener for the current row's gear
mCurrIconRow = ((ExpandableNotificationRow) currView).getSettingsRow();
mCurrIconRow.setGearListener(NotificationStackScrollLayout.this);
-
- // And the translating children
- mTranslatingViews = ((ExpandableNotificationRow) currView).getContentViews();
}
mMoveState = MOVE_STATE_UNDEFINED;
}
@@ -3440,15 +3406,12 @@
}
mMoveState = newMoveState;
- if (view instanceof ExpandableNotificationRow) {
- ((ExpandableNotificationRow) view).setTranslationForOutline(translation);
- if (!isPinnedHeadsUp(view)) {
- // Only show the gear if we're not a heads up view.
- checkForDrag();
- if (mCurrIconRow != null) {
- mCurrIconRow.updateSettingsIcons(translation, getSize(view));
- }
- }
+ final boolean gutsExposed = (view instanceof ExpandableNotificationRow)
+ && ((ExpandableNotificationRow) view).areGutsExposed();
+
+ if (!isPinnedHeadsUp(view) && !gutsExposed) {
+ // Only show the gear if we're not a heads up view and guts aren't exposed.
+ checkForDrag();
}
}
@@ -3471,12 +3434,12 @@
(!fromLeft && absTrans >= snapBackThreshold * 0.4f
&& absTrans <= notiThreshold);
- if (pastGear && !isPinnedHeadsUp(animView)) {
+ if (pastGear && !isPinnedHeadsUp(animView)
+ && (animView instanceof ExpandableNotificationRow)) {
// bouncity
final float target = fromLeft ? snapBackThreshold : -snapBackThreshold;
mGearExposedView = mTranslatingParentView;
- if (mGearDisplayedListener != null
- && (animView instanceof ExpandableNotificationRow)) {
+ if (mGearDisplayedListener != null) {
mGearDisplayedListener.onGearDisplayed((ExpandableNotificationRow) animView);
}
super.snapChild(animView, target, velocity);
@@ -3486,38 +3449,16 @@
}
@Override
- public void onTranslationUpdate(View animView, float value, boolean canBeDismissed) {
- if (mDismissAllInProgress) {
- // When dismissing all, we translate the entire view instead.
- super.onTranslationUpdate(animView, value, canBeDismissed);
- return;
- }
- if (animView instanceof ExpandableNotificationRow) {
- ((ExpandableNotificationRow) animView).setTranslationForOutline(value);
- }
- if (mCurrIconRow != null) {
- mCurrIconRow.updateSettingsIcons(value, getSize(animView));
- }
- }
-
- @Override
public Animator getViewTranslationAnimator(View v, float target,
AnimatorUpdateListener listener) {
if (mDismissAllInProgress) {
// When dismissing all, we translate the entire view instead.
return super.getViewTranslationAnimator(v, target, listener);
+ } else if (v instanceof ExpandableNotificationRow) {
+ return ((ExpandableNotificationRow) v).getTranslateViewAnimator(target, listener);
+ } else {
+ return super.getViewTranslationAnimator(v, target, listener);
}
- ArrayList<Animator> animators = new ArrayList<Animator>();
- for (int i = 0; i < mTranslatingViews.size(); i++) {
- ObjectAnimator anim = createTranslationAnimation(mTranslatingViews.get(i), target);
- animators.add(anim);
- if (i == 0 && listener != null) {
- anim.addUpdateListener(listener);
- }
- }
- AnimatorSet set = new AnimatorSet();
- set.playTogether(animators);
- return set;
}
@Override
@@ -3525,13 +3466,8 @@
if (mDismissAllInProgress) {
// When dismissing all, we translate the entire view instead.
super.setTranslation(v, translate);
- return;
- }
- // Translate the group of views
- for (int i = 0; i < mTranslatingViews.size(); i++) {
- if (mTranslatingViews.get(i) != null) {
- super.setTranslation(mTranslatingViews.get(i), translate);
- }
+ } else {
+ ((ExpandableView) v).setTranslation(translate);
}
}
@@ -3540,15 +3476,11 @@
if (mDismissAllInProgress) {
// When dismissing all, we translate the entire view instead.
return super.getTranslation(v);
+ } else {
+ return ((ExpandableView) v).getTranslation();
}
- // All of the views in the list should have same translation, just use first one.
- if (mTranslatingViews.size() > 0) {
- return super.getTranslation(mTranslatingViews.get(0));
- }
- return 0;
}
-
/**
* Returns the horizontal space in pixels required to display the gear behind a
* notification.
@@ -3603,26 +3535,11 @@
final View prevGearExposedView = mGearExposedView;
mGearExposedView = null;
- AnimatorListenerAdapter listener = new AnimatorListenerAdapter() {
- public void onAnimationEnd(Animator animator) {
- if (prevGearExposedView instanceof ExpandableNotificationRow) {
- ((ExpandableNotificationRow) prevGearExposedView).getSettingsRow()
- .resetState();
- }
- }
- };
- AnimatorUpdateListener updateListener = new AnimatorUpdateListener() {
- @Override
- public void onAnimationUpdate(ValueAnimator animation) {
- if (prevGearExposedView instanceof ExpandableNotificationRow) {
- ((ExpandableNotificationRow) prevGearExposedView)
- .setTranslationForOutline((float) animation.getAnimatedValue());
- }
- }
- };
- Animator set = getViewTranslationAnimator(prevGearExposedView, 0, updateListener);
- set.addListener(listener);
- set.start();
+ Animator anim = getViewTranslationAnimator(prevGearExposedView,
+ 0 /* leftTarget */, null /* updateListener */);
+ if (anim != null) {
+ anim.start();
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
index eea923f..4c94fe9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
@@ -52,13 +52,8 @@
private StackIndentationFunctor mBottomStackIndentationFunctor;
private StackScrollAlgorithmState mTempAlgorithmState = new StackScrollAlgorithmState();
- private boolean mIsExpansionChanging;
- private int mFirstChildMaxHeight;
private boolean mIsExpanded;
- private ExpandableView mFirstChildWhileExpanding;
- private boolean mExpandedOnStart;
private int mBottomStackSlowDownLength;
- private int mCollapseSecondCardPadding;
public StackScrollAlgorithm(Context context) {
initView(context);
@@ -86,8 +81,6 @@
mZBasicHeight = (MAX_ITEMS_IN_BOTTOM_STACK + 1) * mZDistanceBetweenElements;
mBottomStackSlowDownLength = context.getResources()
.getDimensionPixelSize(R.dimen.bottom_stack_slow_down_length);
- mCollapseSecondCardPadding = context.getResources().getDimensionPixelSize(
- R.dimen.notification_collapse_second_card_padding);
mBottomStackIndentationFunctor = new PiecewiseLinearIndentationFunctor(
MAX_ITEMS_IN_BOTTOM_STACK,
mBottomStackPeekSize,
@@ -508,7 +501,7 @@
int childHeight, int minHeight, AmbientState ambientState) {
int bottomStackStart = ambientState.getInnerHeight()
- - mBottomStackPeekSize - mCollapseSecondCardPadding;
+ - mBottomStackPeekSize - mBottomStackSlowDownLength;
int childStart = bottomStackStart - childHeight;
if (childStart < childViewState.yTranslation) {
float newHeight = bottomStackStart - childViewState.yTranslation;
@@ -595,12 +588,9 @@
// The starting position of the bottom stack peek
int bottomPeekStart = ambientState.getInnerHeight() - mBottomStackPeekSize -
- mCollapseSecondCardPadding + ambientState.getScrollY();
+ mBottomStackSlowDownLength + ambientState.getScrollY();
// Collapse and expand the first child while the shade is being expanded
- float maxHeight = mIsExpansionChanging && child == mFirstChildWhileExpanding
- ? mFirstChildMaxHeight
- : childHeight;
- childViewState.height = (int) Math.max(Math.min(bottomPeekStart, maxHeight),
+ childViewState.height = (int) Math.max(Math.min(bottomPeekStart, (float) childHeight),
child.getMinHeight());
}
@@ -656,55 +646,6 @@
}
}
- public void onExpansionStarted(StackScrollState currentState) {
- mIsExpansionChanging = true;
- mExpandedOnStart = mIsExpanded;
- ViewGroup hostView = currentState.getHostView();
- updateFirstChildHeightWhileExpanding(hostView);
- }
-
- private void updateFirstChildHeightWhileExpanding(ViewGroup hostView) {
- mFirstChildWhileExpanding = (ExpandableView) findFirstVisibleChild(hostView);
- if (mFirstChildWhileExpanding != null) {
- if (mExpandedOnStart) {
-
- // We are collapsing the shade, so the first child can get as most as high as the
- // current height or the end value of the animation.
- mFirstChildMaxHeight = StackStateAnimator.getFinalActualHeight(
- mFirstChildWhileExpanding);
- } else {
- updateFirstChildMaxSizeToMaxHeight();
- }
- } else {
- mFirstChildMaxHeight = 0;
- }
- }
-
- private void updateFirstChildMaxSizeToMaxHeight() {
- // We are expanding the shade, expand it to its full height.
- if (!isMaxSizeInitialized(mFirstChildWhileExpanding)) {
-
- // This child was not layouted yet, wait for a layout pass
- mFirstChildWhileExpanding
- .addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
- @Override
- public void onLayoutChange(View v, int left, int top, int right,
- int bottom, int oldLeft, int oldTop, int oldRight,
- int oldBottom) {
- if (mFirstChildWhileExpanding != null) {
- mFirstChildMaxHeight = getMaxAllowedChildHeight(
- mFirstChildWhileExpanding);
- } else {
- mFirstChildMaxHeight = 0;
- }
- v.removeOnLayoutChangeListener(this);
- }
- });
- } else {
- mFirstChildMaxHeight = getMaxAllowedChildHeight(mFirstChildWhileExpanding);
- }
- }
-
private boolean isMaxSizeInitialized(ExpandableView child) {
if (child instanceof ExpandableNotificationRow) {
ExpandableNotificationRow row = (ExpandableNotificationRow) child;
@@ -724,32 +665,10 @@
return null;
}
- public void onExpansionStopped() {
- mIsExpansionChanging = false;
- mFirstChildWhileExpanding = null;
- }
-
public void setIsExpanded(boolean isExpanded) {
this.mIsExpanded = isExpanded;
}
- public void notifyChildrenChanged(final NotificationStackScrollLayout hostView) {
- if (mIsExpansionChanging) {
- hostView.post(new Runnable() {
- @Override
- public void run() {
- updateFirstChildHeightWhileExpanding(hostView);
- }
- });
- }
- }
-
- public void onReset(ExpandableView view) {
- if (view.equals(mFirstChildWhileExpanding)) {
- updateFirstChildMaxSizeToMaxHeight();
- }
- }
-
class StackScrollAlgorithmState {
/**
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/NightModeTile.java b/packages/SystemUI/src/com/android/systemui/tuner/NightModeTile.java
index 61135bd..26e1d46 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/NightModeTile.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/NightModeTile.java
@@ -20,6 +20,8 @@
import android.provider.Settings;
import com.android.internal.logging.MetricsProto.MetricsEvent;
+import com.android.systemui.Prefs;
+import com.android.systemui.Prefs.Key;
import com.android.systemui.R;
import com.android.systemui.qs.QSTile;
import com.android.systemui.statusbar.policy.NightModeController;
@@ -46,6 +48,12 @@
}
@Override
+ public boolean isAvailable() {
+ return Prefs.getBoolean(mContext, Key.QS_NIGHT_ADDED, false)
+ && TunerService.isTunerEnabled(mContext);
+ }
+
+ @Override
public void setListening(boolean listening) {
if (listening) {
mNightModeController.addListener(this);
diff --git a/packages/SystemUI/src/com/android/systemui/tv/pip/PipMenuActivity.java b/packages/SystemUI/src/com/android/systemui/tv/pip/PipMenuActivity.java
index fb7fa4d..fb425ab 100644
--- a/packages/SystemUI/src/com/android/systemui/tv/pip/PipMenuActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/tv/pip/PipMenuActivity.java
@@ -25,6 +25,9 @@
import android.widget.TextView;
import com.android.systemui.R;
+import com.android.systemui.SystemUI;
+import com.android.systemui.SystemUIApplication;
+import com.android.systemui.recents.Recents;
import static android.content.pm.PackageManager.FEATURE_LEANBACK;
import static android.content.pm.PackageManager.FEATURE_PICTURE_IN_PICTURE;
@@ -47,6 +50,7 @@
private TextView mPlayPauseDescriptionTextView;
private View mCloseButtonView;
private View mCloseDescriptionView;
+ private boolean mMovePipToFullscreen;
private MediaController.Callback mMediaControllerCallback = new MediaController.Callback() {
@Override
@@ -66,6 +70,7 @@
@Override
public void onClick(View v) {
mPipManager.movePipToFullscreen();
+ mMovePipToFullscreen = true;
finish();
}
});
@@ -164,7 +169,9 @@
}
private void restorePipAndFinish() {
- mPipManager.resizePinnedStack(PipManager.STATE_PIP_OVERLAY);
+ if (!mMovePipToFullscreen) {
+ mPipManager.resizePinnedStack(PipManager.STATE_PIP_OVERLAY);
+ }
finish();
}
@@ -214,4 +221,18 @@
mPipManager.suspendPipResizing(
PipManager.SUSPEND_PIP_RESIZE_REASON_WAITING_FOR_MENU_ACTIVITY_FINISH);
}
+
+ @Override
+ public void finish() {
+ super.finish();
+ if (mPipManager.isRecentsShown() && !mMovePipToFullscreen) {
+ SystemUI[] services = ((SystemUIApplication) getApplication()).getServices();
+ for (int i = services.length - 1; i >= 0; i--) {
+ if (services[i] instanceof Recents) {
+ ((Recents) services[i]).showRecents(false, null);
+ break;
+ }
+ }
+ }
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
index ebd5384..60d33fa 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
@@ -32,6 +32,7 @@
import com.android.settingslib.net.DataUsageController;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.statusbar.policy.NetworkController.IconState;
+import com.android.systemui.statusbar.policy.NetworkController.SignalCallback;
import com.android.systemui.statusbar.policy.NetworkControllerImpl.Config;
import com.android.systemui.statusbar.policy.NetworkControllerImpl.SubscriptionDefaults;
import org.mockito.ArgumentCaptor;
@@ -100,7 +101,7 @@
// Trigger blank callbacks to always get the current state (some tests don't trigger
// changes from default state).
- mNetworkController.addSignalCallback(null);
+ mNetworkController.addSignalCallback(mock(SignalCallback.class));
mNetworkController.addEmergencyListener(null);
}
diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto
index 077b121..8171b49 100644
--- a/proto/src/metrics_constants.proto
+++ b/proto/src/metrics_constants.proto
@@ -24,334 +24,1734 @@
// Known visual elements: views or controls.
enum View {
+ // Unknown view
VIEW_UNKNOWN = 0;
+
+ // OBSOLETE
MAIN_SETTINGS = 1;
+
+ // OPEN: Settings > Accessibility
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
ACCESSIBILITY = 2;
+
+ // OPEN: Settings > Accessibility > Captions
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
ACCESSIBILITY_CAPTION_PROPERTIES = 3;
+
+ // OPEN: Settings > Accessibility > [Service]
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
ACCESSIBILITY_SERVICE = 4;
+
+ // OPEN: Settings > Accessibility > Color correction
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
ACCESSIBILITY_TOGGLE_DALTONIZER = 5;
+
+ // OPEN: Settings > Accessibility > Accessibility shortcut
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
ACCESSIBILITY_TOGGLE_GLOBAL_GESTURE = 6;
+
+ // OPEN: Settings > Accessibility > Magnification gestures
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
ACCESSIBILITY_TOGGLE_SCREEN_MAGNIFICATION = 7;
+
+ // OPEN: Settings > Accounts
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
ACCOUNT = 8;
+
+ // OPEN: Settings > Accounts > [Single Account Sync Settings]
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
ACCOUNTS_ACCOUNT_SYNC = 9;
+
+ // OPEN: Settings > Accounts > Add an account
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
ACCOUNTS_CHOOSE_ACCOUNT_ACTIVITY = 10;
+
+ // OPEN: Settings > Accounts > [List of accounts when more than one]
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
ACCOUNTS_MANAGE_ACCOUNTS = 11;
+
+ // OPEN: Settings > Cellular network settings > APNs
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
APN = 12;
+
+ // OPEN: Settings > More > Cellular network settings > APNs > [Edit APN]
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
APN_EDITOR = 13;
+
+ // OBSOLETE
APP_OPS_DETAILS = 14;
+
+ // OBSOLETE
APP_OPS_SUMMARY = 15;
+
+ // OBSOLETE
APPLICATION = 16;
+
+ // OPEN: Settings > Apps > Configure apps > App links > [App]
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
APPLICATIONS_APP_LAUNCH = 17;
+
+ // OBSOLETE
APPLICATIONS_APP_PERMISSION = 18;
+
+ // OPEN: Settings > Internal storage > Apps storage > [App]
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
APPLICATIONS_APP_STORAGE = 19;
+
+ // OPEN: Settings > Apps > [App info]
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
APPLICATIONS_INSTALLED_APP_DETAILS = 20;
+
+ // OPEN: Settings > Memory > App usage > [App Memory usage]
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
APPLICATIONS_PROCESS_STATS_DETAIL = 21;
+
+ // OBSOLETE
APPLICATIONS_PROCESS_STATS_MEM_DETAIL = 22;
+
+ // OPEN: Settings > Memory > App usage
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
APPLICATIONS_PROCESS_STATS_UI = 23;
+
+ // OPEN: Settings > Bluetooth
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
BLUETOOTH = 24;
+
+ // OPEN: Choose Bluetooth device (ex: when sharing)
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
BLUETOOTH_DEVICE_PICKER = 25;
+
+ // OBSOLETE
BLUETOOTH_DEVICE_PROFILES = 26;
+
+ // OPEN: Settings > Security > Choose screen lock
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
CHOOSE_LOCK_GENERIC = 27;
+
+ // OPEN: Settings > Security > Choose screen lock > Choose your password
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
CHOOSE_LOCK_PASSWORD = 28;
+
+ // OPEN: Settings > Security > Choose screen lock > Choose your pattern
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
CHOOSE_LOCK_PATTERN = 29;
+
+ // OPEN: Settings > Security > Choose screen lock > Confirm your password
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
CONFIRM_LOCK_PASSWORD = 30;
+
+ // OPEN: Settings > Security > Choose screen lock > Confirm your pattern
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
CONFIRM_LOCK_PATTERN = 31;
+
+ // OPEN: Settings > Security > Encrypt phone
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
CRYPT_KEEPER = 32;
+
+ // OPEN: Settings > Security > Encrypt phone > Confirm
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
CRYPT_KEEPER_CONFIRM = 33;
+
+ // OPEN: Settings > Search results
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
DASHBOARD_SEARCH_RESULTS = 34;
+
+ // OPEN: Settings (Root page)
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
DASHBOARD_SUMMARY = 35;
+
+ // OBSOLETE
DATA_USAGE = 36;
+
+ // OPEN: Settings > Data usage
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
DATA_USAGE_SUMMARY = 37;
+
+ // OPEN: Settings > Date & time
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
DATE_TIME = 38;
+
+ // OPEN: Settings > Developer options
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
DEVELOPMENT = 39;
+
+ // OPEN: Settings > About phone
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
DEVICEINFO = 40;
+
+ // OPEN: Settings > About phone > Status > IMEI information
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
DEVICEINFO_IMEI_INFORMATION = 41;
+
+ // OPEN: Settings > Internal storage
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
DEVICEINFO_STORAGE = 42;
+
+ // OPEN: Settings > About phone > Status > SIM status
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
DEVICEINFO_SIM_STATUS = 43;
+
+ // OPEN: Settings > About phone > Status
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
DEVICEINFO_STATUS = 44;
+
+ // OBSOLETE
DEVICEINFO_USB = 45;
+
+ // OPEN: Settings > Display
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
DISPLAY = 46;
+
+ // OPEN: Settings > Display > Daydream
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
DREAM = 47;
+
+ // OPEN: Settings > Security > Screen lock > Secure start-up
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
ENCRYPTION = 48;
+
+ // OPEN: Settings > Security > Nexus Imprint
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
FINGERPRINT = 49;
+
+ // OBSOLETE
FINGERPRINT_ENROLL = 50;
+
+ // OPEN: Settings > Battery > History details
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
FUELGAUGE_BATTERY_HISTORY_DETAIL = 51;
+
+ // OPEN: Settings > Battery > Battery saver
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
FUELGAUGE_BATTERY_SAVER = 52;
+
+ // OPEN: Settings > Battery > [App Use details]
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
FUELGAUGE_POWER_USAGE_DETAIL = 53;
+
+ // OPEN: Settings > Battery
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
FUELGAUGE_POWER_USAGE_SUMMARY = 54;
+
+ // OPEN: Settings > Home
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
HOME = 55;
+
+ // OPEN: Settings > Security > SIM card lock settings
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
ICC_LOCK = 56;
+
+ // OPEN: Settings > Language & input
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
INPUTMETHOD_LANGUAGE = 57;
+
+ // OPEN: Settings > Language & input > Physical keyboard
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
INPUTMETHOD_KEYBOARD = 58;
+
+ // OPEN: Settings > Language & input > Spell checker
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
INPUTMETHOD_SPELL_CHECKERS = 59;
+
+ // OBSOLETE
INPUTMETHOD_SUBTYPE_ENABLER = 60;
+
+ // OPEN: Settings > Language & input > Personal dictionary
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
INPUTMETHOD_USER_DICTIONARY = 61;
+
+ // OPEN: Settings > Language & input > Add word
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
INPUTMETHOD_USER_DICTIONARY_ADD_WORD = 62;
+
+ // OPEN: Settings > Location
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
LOCATION = 63;
+
+ // OPEN: Settings > Location > Location mode
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
LOCATION_MODE = 64;
+
+ // OPEN: Settings > Apps
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
MANAGE_APPLICATIONS = 65;
+
+ // OPEN: Settings > Backup & reset > Factory data reset
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
MASTER_CLEAR = 66;
+
+ // OPEN: Settings > Backup & reset > Factory data reset > Confirm
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
MASTER_CLEAR_CONFIRM = 67;
+
+ // OPEN: Settings > Data usage > Network restrictions
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
NET_DATA_USAGE_METERED = 68;
+
+ // OPEN: Settings > More > Android Beam
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
NFC_BEAM = 69;
+
+ // OPEN: Settings > Tap & pay
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
NFC_PAYMENT = 70;
+
+ // OPEN: Settings > Sound & notification
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
NOTIFICATION = 71;
+
+ // OPEN: Settings > Sound & notification > App notifications > [App]
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
NOTIFICATION_APP_NOTIFICATION = 72;
+
+ // OPEN: Settings > Sound & notification > Other sounds
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
NOTIFICATION_OTHER_SOUND = 73;
+
+ // OBSOLETE
NOTIFICATION_REDACTION = 74;
+
+ // OPEN: Settings Widget > Notification log
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
NOTIFICATION_STATION = 75;
+
+ // OPEN: Settings > Sound & notification > Do not disturb
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
NOTIFICATION_ZEN_MODE = 76;
+
+ // OPEN: OBSOLETE
OWNER_INFO = 77;
+
+ // OPEN: Print job notification > Print job settings
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
PRINT_JOB_SETTINGS = 78;
+
+ // OPEN: Settings > Printing > [Print Service]
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
PRINT_SERVICE_SETTINGS = 79;
+
+ // OPEN: Settings > Printing
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
PRINT_SETTINGS = 80;
+
+ // OPEN: Settings > Backup & reset
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
PRIVACY = 81;
+
+ //OBSOLETE
PROXY_SELECTOR = 82;
+
+ // OPEN: Settings > Backup & reset > Network settings reset
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
RESET_NETWORK = 83;
+
+ // OPEN: Settings > Backup & reset > Network settings reset > Confirm
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
RESET_NETWORK_CONFIRM = 84;
+
+ // OPEN: Settings > Developer Options > Running Services
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
RUNNING_SERVICE_DETAILS = 85;
+
+ // OPEN: Settings > Security > Screen pinning
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
SCREEN_PINNING = 86;
+
+ // OPEN: Settings > Security
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
SECURITY = 87;
+
+ // OPEN: Settings > SIM cards
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
SIM = 88;
+
+ // OBSOLETE
TESTING = 89;
+
+ // OPEN: Settings > More > Tethering & portable hotspot
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
TETHER = 90;
+
+ // OPEN: Settings > Security > Trust agents
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
TRUST_AGENT = 91;
+
+ // OPEN: Settings > Security > Trusted credentials
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
TRUSTED_CREDENTIALS = 92;
+
+ // OPEN: Settings > Language & input > TTS output > [Engine] > Settings
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
TTS_ENGINE_SETTINGS = 93;
+
+ // OPEN: Settings > Language & input > Text-to-speech output
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
TTS_TEXT_TO_SPEECH = 94;
+
+ // OPEN: Settings > Security > Apps with usage access
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
USAGE_ACCESS = 95;
+
+ // OPEN: Settings > Users
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
USER = 96;
+
+ // OPEN: Settings > Users > [Restricted profile app & content access]
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
USERS_APP_RESTRICTIONS = 97;
+
+ // OPEN: Settings > Users > [User settings]
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
USER_DETAILS = 98;
+
+ // OBSOLETE
VOICE_INPUT = 99;
+
+ // OPEN: Settings > More > VPN
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
VPN = 100;
+
+ // OPEN: Settings > Display > Choose wallpaper from
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
WALLPAPER_TYPE = 101;
+
+ // OPEN: Settings > Display > Cast
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
WFD_WIFI_DISPLAY = 102;
+
+ // OPEN: Settings > Wi-Fi
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
WIFI = 103;
+
+ // OPEN: Settings > Wi-Fi > Advanced Wi-Fi
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
WIFI_ADVANCED = 104;
+
+ // OPEN: Settings > More > Wi-Fi Calling
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
WIFI_CALLING = 105;
+
+ // OPEN: Settings > Wi-Fi > Saved networks
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
WIFI_SAVED_ACCESS_POINTS = 106;
+
+ // OBSOLETE
WIFI_APITEST = 107;
+
+ // OBSOLETE
WIFI_INFO = 108;
+
+ // OPEN: Settings > Wi-Fi > Advanced Wi-Fi > Wi-Fi Direct
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
WIFI_P2P = 109;
+
+ // OPEN: Settings > More
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
WIRELESS = 110;
+
+ // OPEN: Quick Settings Panel
+ // CATEGORY: QUICK_SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
QS_PANEL = 111;
+
+ // OPEN: QS Airplane mode tile shown
+ // ACTION: QS Airplane mode tile tapped
+ // SUBTYPE: 0 is off, 1 is on
+ // CATEGORY: QUICK_SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.46
QS_AIRPLANEMODE = 112;
+
+ // OPEN: QS Bluetooth tile shown
+ // ACTION: QS Bluetooth tile tapped
+ // SUBTYPE: 0 is off, 1 is on
+ // CATEGORY: QUICK_SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.46
QS_BLUETOOTH = 113;
+
+ // OPEN: QS Cast tile shown
+ // ACTION: QS Cast tile tapped
+ // CATEGORY: QUICK_SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.46
QS_CAST = 114;
+
+ // OPEN: QS Cellular tile shown
+ // ACTION: QS Cellular tile tapped
+ // CATEGORY: QUICK_SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.46
QS_CELLULAR = 115;
+
+ // OPEN: QS Color inversion tile shown
+ // ACTION: QS Color inversion tile tapped
+ // SUBTYPE: 0 is off, 1 is on
+ // CATEGORY: QUICK_SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.46
QS_COLORINVERSION = 116;
+
+ // OPEN: QS Cellular tile > Cellular detail panel
+ // CATEGORY: QUICK_SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.46
QS_DATAUSAGEDETAIL = 117;
+
+ // OPEN: QS Do not disturb tile shown
+ // ACTION: QS Do not disturb tile tapped
+ // SUBTYPE: 0 is off, 1 is on
+ // CATEGORY: QUICK_SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.46
QS_DND = 118;
+
+ // OPEN: QS Flashlight tile shown
+ // ACTION: QS Flashlight tile tapped
+ // SUBTYPE: 0 is off, 1 is on
+ // CATEGORY: QUICK_SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.46
QS_FLASHLIGHT = 119;
+
+ // OPEN: QS Hotspot tile shown
+ // ACTION: QS Hotspot tile tapped
+ // SUBTYPE: 0 is off, 1 is on
+ // CATEGORY: QUICK_SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.46
QS_HOTSPOT = 120;
+
+ // OPEN: QS 3P tile shown
+ // ACTION: QS 3P tile tapped
+ // CATEGORY: QUICK_SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.46
QS_INTENT = 121;
+
+ // OPEN: QS Location tile shown
+ // ACTION: QS Location tile tapped
+ // SUBTYPE: 0 is off, 1 is on
+ // CATEGORY: QUICK_SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.46
QS_LOCATION = 122;
+
+ // OPEN: QS Rotation tile shown
+ // ACTION: QS Rotation tile tapped
+ // SUBTYPE: 0 is off, 1 is on
+ // CATEGORY: QUICK_SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.46
QS_ROTATIONLOCK = 123;
+
+ // OBSOLETE
QS_USERDETAILITE = 124;
+
+ // OPEN: QS User list panel
+ // CATEGORY: QUICK_SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.46
QS_USERDETAIL = 125;
+
+ // OPEN: QS WiFi tile shown
+ // ACTION: QS WiFi tile tapped
+ // SUBTYPE: 0 is off, 1 is on
+ // CATEGORY: QUICK_SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.46
QS_WIFI = 126;
+
+ // OPEN: Notification Panel (including lockscreen)
+ // CATEGORY: NOTIFICATION
+ // OS: 5.1.1
+ // GMS: 7.5.26
NOTIFICATION_PANEL = 127;
+
+ // OPEN: Notification in panel became visible.
+ // PACKAGE: App that posted the notification.
+ // ACTION: Notification is tapped.
+ // PACKAGE: App that posted the notification
+ // DETAIL: Notification is expanded by user.
+ // PACKAGE: App that posted the notification
+ // DISMISS: Notification is dismissed.
+ // PACKAGE: App that posted the notification
+ // SUBTYPE: Dismiss reason from NotificationManagerService.java
+ // CATEGORY: NOTIFICATION
+ // OS: 5.1.1
+ // GMS: 7.5.26
NOTIFICATION_ITEM = 128;
+
+ // ACTION: User tapped notification action
+ // PACKAGE: App that posted the notification
+ // SUBTYPE: Index of action on notification
+ // CATEGORY: NOTIFICATION
+ // OS: 5.0
+ // GMS: 7.5.26
NOTIFICATION_ITEM_ACTION = 129;
+
+ // OPEN: Settings > Apps > Configure apps > App permissions
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
APPLICATIONS_ADVANCED = 130;
+
+ // OPEN: Settings > Location > Scanning
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
LOCATION_SCANNING = 131;
+
+ // OBSOLETE
MANAGE_APPLICATIONS_ALL = 132;
+
+ // OPEN: Settings > Sound & notification > App notifications
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
MANAGE_APPLICATIONS_NOTIFICATIONS = 133;
+
+ // ACTION: Settings > Wi-Fi > Overflow > Add Network
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
ACTION_WIFI_ADD_NETWORK = 134;
+
+ // ACTION: Settings > Wi-Fi > [Long press network] > Connect to network
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
ACTION_WIFI_CONNECT = 135;
+
+ // ACTION: Settings > Wi-Fi > Overflow > Refresh
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
ACTION_WIFI_FORCE_SCAN = 136;
+
+ // ACTION: Settings > Wi-Fi > [Long press network] > Forget network
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
ACTION_WIFI_FORGET = 137;
+
+ // ACTION: Settings > Wi-Fi > Toggle off
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
ACTION_WIFI_OFF = 138;
+
+ // ACTION: Settings > Wi-Fi > Toggle on
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
ACTION_WIFI_ON = 139;
+
+ // OBSOLETE
MANAGE_PERMISSIONS = 140;
+
+ // OPEN: Settings > Sound & notification > DND > Priority only allows
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
NOTIFICATION_ZEN_MODE_PRIORITY = 141;
+
+ // OPEN: Settings > Sound & notification > DND > Automatic rules
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
NOTIFICATION_ZEN_MODE_AUTOMATION = 142;
+
+ // OPEN: Settings > Apps > Configure apps > App links
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
MANAGE_DOMAIN_URLS = 143;
+
+ // OPEN: Settings > Sound & notification > DND > [Time based rule]
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
NOTIFICATION_ZEN_MODE_SCHEDULE_RULE = 144;
+
+ // OPEN: Settings > Sound & notification > DND > [External rule]
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
NOTIFICATION_ZEN_MODE_EXTERNAL_RULE = 145;
+
+ // OPEN: Settings > Sound & notification > DND > [Event rule]
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
NOTIFICATION_ZEN_MODE_EVENT_RULE = 146;
+
+ // ACTION: App notification settings > Block Notifications
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
ACTION_BAN_APP_NOTES = 147;
+
+ // ACTION: Notification shade > Dismiss all button
+ // CATEGORY: NOTIFICATION
+ // OS: 6.0
+ // GMS: 7.5.26
ACTION_DISMISS_ALL_NOTES = 148;
+
+ // OPEN: QS Do Not Disturb detail panel
+ // CATEGORY: QUICK_SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
QS_DND_DETAILS = 149;
+
+ // OPEN: QS Bluetooth detail panel
+ // CATEGORY: QUICK_SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
QS_BLUETOOTH_DETAILS = 150;
+
+ // OPEN: QS Cast detail panel
+ // CATEGORY: QUICK_SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
QS_CAST_DETAILS = 151;
+
+ // OPEN: QS Wi-Fi detail panel
+ // CATEGORY: QUICK_SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
QS_WIFI_DETAILS = 152;
+
+ // ACTION: QS Wi-Fi detail panel > Wi-Fi toggle
+ // SUBTYPE: 0 is off, 1 is on
+ // CATEGORY: QUICK_SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
QS_WIFI_TOGGLE = 153;
+
+ // ACTION: QS Bluetooth detail panel > Bluetooth toggle
+ // SUBTYPE: 0 is off, 1 is on
+ // CATEGORY: QUICK_SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
QS_BLUETOOTH_TOGGLE = 154;
+
+ // ACTION: QS Cellular detail panel > Cellular toggle
+ // SUBTYPE: 0 is off, 1 is on
+ // CATEGORY: QUICK_SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
QS_CELLULAR_TOGGLE = 155;
+
+ // ACTION: QS User list panel > Select different user
+ // CATEGORY: QUICK_SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
QS_SWITCH_USER = 156;
+
+ // ACTION: QS Cast detail panel > Select cast device
+ // CATEGORY: QUICK_SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
QS_CAST_SELECT = 157;
+
+ // ACTION: QS Cast detail panel > Disconnect cast device
+ // CATEGORY: QUICK_SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
QS_CAST_DISCONNECT = 158;
+
+ // ACTION: Settings > Bluetooth > Toggle
+ // SUBTYPE: 0 is off, 1 is on
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
ACTION_BLUETOOTH_TOGGLE = 159;
+
+ // ACTION: Settings > Bluetooth > Overflow > Refresh
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
ACTION_BLUETOOTH_SCAN = 160;
+
+ // ACTION: Settings > Bluetooth > Overflow > Rename this device
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
ACTION_BLUETOOTH_RENAME = 161;
+
+ // ACTION: Settings > Bluetooth > Overflow > Show received files
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
ACTION_BLUETOOTH_FILES = 162;
+
+ // ACTION: QS DND details panel > Increase / Decrease exit time
+ // SUBTYPE: true is increase, false is decrease
+ // CATEGORY: QUICK_SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
QS_DND_TIME = 163;
+
+ // ACTION: QS DND details panel > [Exit condition]
+ // CATEGORY: QUICK_SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
QS_DND_CONDITION_SELECT = 164;
+
+ // ACTION: QS DND details panel > [DND mode]
+ // SUBTYPE: 1 is priority, 2 is silence, 3 is alarms only
+ // CATEGORY: QUICK_SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
QS_DND_ZEN_SELECT = 165;
+
+ // ACTION: QS DND detail panel > DND toggle
+ // SUBTYPE: 0 is off, 1 is on
+ // CATEGORY: QUICK_SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
QS_DND_TOGGLE = 166;
+
+ // ACTION: DND Settings > Priority only allows > Reminder toggle
+ // SUBTYPE: 0 is off, 1 is on
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
ACTION_ZEN_ALLOW_REMINDERS = 167;
+
+ // ACTION: DND Settings > Priority only allows > Event toggle
+ // SUBTYPE: 0 is off, 1 is on
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
ACTION_ZEN_ALLOW_EVENTS = 168;
+
+ // ACTION: DND Settings > Priority only allows > Messages
+ // SUBTYPE: 0 is off, 1 is on
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
ACTION_ZEN_ALLOW_MESSAGES = 169;
+
+ // ACTION: DND Settings > Priority only allows > Calls
+ // SUBTYPE: 0 is off, 1 is on
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
ACTION_ZEN_ALLOW_CALLS = 170;
+
+ // ACTION: DND Settings > Priority only allows > Repeat callers toggle
+ // SUBTYPE: 0 is off, 1 is on
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
ACTION_ZEN_ALLOW_REPEAT_CALLS = 171;
+
+ // ACTION: DND Settings > Automatic rules > Add rule
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
ACTION_ZEN_ADD_RULE = 172;
+
+ // ACTION: DND Settings > Automatic rules > Add rule > OK
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
ACTION_ZEN_ADD_RULE_OK = 173;
+
+ // ACTION: DND Settings > Automatic rules > [Rule] > Delete rule
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
ACTION_ZEN_DELETE_RULE = 174;
+
+ // ACTION: DND Settings > Automatic rules > [Rule] > Delete rule > Delete
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
ACTION_ZEN_DELETE_RULE_OK = 175;
+
+ // ACTION: DND Settings > Automatic rules > [Rule] > Toggle
+ // SUBTYPE: 0 is off, 1 is on
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
ACTION_ZEN_ENABLE_RULE = 176;
+
+ // ACTION: Settings > More > Airplane mode toggle
+ // SUBTYPE: 0 is off, 1 is on
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
ACTION_AIRPLANE_TOGGLE = 177;
+
+ // ACTION: Settings > Data usage > Cellular data toggle
+ // SUBTYPE: 0 is off, 1 is on
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
ACTION_CELL_DATA_TOGGLE = 178;
+
+ // OPEN: Settings > Sound & notification > Notification access
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
NOTIFICATION_ACCESS = 179;
+
+ // OPEN: Settings > Sound & notification > Do Not Disturb access
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
NOTIFICATION_ZEN_MODE_ACCESS = 180;
+
+ // OPEN: Settings > Apps > Configure apps > Default Apps
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
APPLICATIONS_DEFAULT_APPS = 181;
+
+ // OPEN: Settings > Internal storage > Apps storage
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
APPLICATIONS_STORAGE_APPS = 182;
+
+ // OPEN: Settings > Security > Usage access
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
APPLICATIONS_USAGE_ACCESS_DETAIL = 183;
+
+ // OPEN: Settings > Battery > Battery optimization
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
APPLICATIONS_HIGH_POWER_APPS = 184;
+
+ // OBSOLETE
FUELGAUGE_HIGH_POWER_DETAILS = 185;
+
+ // ACTION: Lockscreen > Unlock gesture
+ // CATEGORY: GLOBAL_SYSTEM_UI
+ // OS: 5.1.1
+ // GMS: 7.8.22
ACTION_LS_UNLOCK = 186;
+
+ // ACTION: Lockscreen > Pull shade open
+ // CATEGORY: GLOBAL_SYSTEM_UI
+ // OS: 5.1.1
+ // GMS: 7.8.22
ACTION_LS_SHADE = 187;
+
+ // ACTION: Lockscreen > Tap on lock, shows hint
+ // CATEGORY: GLOBAL_SYSTEM_UI
+ // OS: 5.1.1
+ // GMS: 7.8.22
ACTION_LS_HINT = 188;
+
+ // ACTION: Lockscreen > Camera
+ // CATEGORY: GLOBAL_SYSTEM_UI
+ // OS: 5.1.1
+ // GMS: 7.8.22
ACTION_LS_CAMERA = 189;
+
+ // ACTION: Lockscreen > Dialer
+ // CATEGORY: GLOBAL_SYSTEM_UI
+ // OS: 5.1.1
+ // GMS: 7.8.22
ACTION_LS_DIALER = 190;
+
+ // ACTION: Lockscreen > Tap on lock, locks phone
+ // CATEGORY: GLOBAL_SYSTEM_UI
+ // OS: 5.1.1
+ // GMS: 7.8.22
ACTION_LS_LOCK = 191;
+
+ // ACTION: Lockscreen > Tap on notification, false touch rejection
+ // CATEGORY: GLOBAL_SYSTEM_UI
+ // OS: 5.1.1
+ // GMS: 7.8.22
ACTION_LS_NOTE = 192;
+
+ // ACTION: Lockscreen > Swipe down to open quick settings
+ // CATEGORY: GLOBAL_SYSTEM_UI
+ // OS: 6.0
+ // GMS: 7.8.22
ACTION_LS_QS = 193;
+
+ // ACTION: Swipe down to open quick settings when unlocked
+ // CATEGORY: GLOBAL_SYSTEM_UI
+ // OS: 6.0
+ // GMS: 7.8.22
ACTION_SHADE_QS_PULL = 194;
+
+ // ACTION: Notification shade > Tap to open quick settings
+ // CATEGORY: GLOBAL_SYSTEM_UI
+ // OS: 6.0
+ // GMS: 7.8.22
ACTION_SHADE_QS_TAP = 195;
+
+ // OPEN: Lockscreen
+ // SUBTYPE: 0 is unsecure, 1 is secured by password / pattern / PIN
+ // CATEGORY: GLOBAL_SYSTEM_UI
+ // OS: 5.1.1
+ // GMS: 7.8.22
LOCKSCREEN = 196;
+
+ // OPEN: Lockscreen > Screen to enter password / pattern / PIN
+ // CATEGORY: GLOBAL_SYSTEM_UI
+ // OS: 5.1.1
+ // GMS: 7.8.22
BOUNCER = 197;
+
+ // OPEN: Screen turned on
+ // SUBTYPE: 2 is user action
+ // CATEGORY: GLOBAL_SYSTEM_UI
+ // OS: 5.1.1
+ // GMS: 7.8.22
SCREEN = 198;
+
+ // OPEN: Notification caused sound, vibration, and/or LED blink
+ // SUBTYPE: 1 is buzz, 2 is beep, blink is 4, or'd together
+ // CATEGORY: NOTIFICATION
+ // OS: 5.1.1
+ // GMS: 7.8.53
NOTIFICATION_ALERT = 199;
+
+ // ACTION: Lockscreen > Emergency Call button
+ // CATEGORY: GLOBAL_SYSTEM_UI
+ // OS: 5.1.1
+ // GMS: 7.5.26
ACTION_EMERGENCY_CALL = 200;
+
+ // OPEN: Settings > Apps > Configure > Default apps > Assist & voice input
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
APPLICATIONS_MANAGE_ASSIST = 201;
+
+ // OPEN: Settings > Memory
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
PROCESS_STATS_SUMMARY = 202;
+
+ // ACTION: Settings > Display > When device is rotated
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
ACTION_ROTATION_LOCK = 203;
+
+ // ACTION: Long press on notification to view controls
+ // CATEGORY: NOTIFICATION
+ // OS: 6.0
+ // GMS: 7.5.26
ACTION_NOTE_CONTROLS = 204;
+
+ // ACTION: Notificatoin controls > Info button
+ // CATEGORY: NOTIFICATION
+ // OS: 6.0
+ // GMS: 7.5.26
ACTION_NOTE_INFO = 205;
+
+ // ACTION: Notification controls > Settings button
+ // CATEGORY: NOTIFICATION
+ // OS: 6.0
+ // GMS: 7.5.26
ACTION_APP_NOTE_SETTINGS = 206;
+
+ // OPEN: Volume Dialog (with hardware buttons)
+ // CATEGORY: GLOBAL_SYSTEM_UI
+ // OS: 6.0
+ // GMS: 7.5.26
VOLUME_DIALOG = 207;
+
+ // OPEN: Volume dialog > Expanded volume dialog (multiple sliders)
+ // CATEGORY: GLOBAL_SYSTEM_UI
+ // OS: 6.0
+ // GMS: 7.5.26
VOLUME_DIALOG_DETAILS = 208;
+
+ // ACTION: Volume dialog > Adjust volume slider
+ // SUBTYPE: volume level (0-7)
+ // CATEGORY: GLOBAL_SYSTEM_UI
+ // OS: 6.0
+ // GMS: 7.5.26
ACTION_VOLUME_SLIDER = 209;
+
+ // ACTION: Volume dialog > Select non-active stream
+ // SUBTYPE: stream (defined in AudioSystem.java)
+ // CATEGORY: GLOBAL_SYSTEM_UI
+ // OS: 6.0
+ // GMS: 7.5.26
ACTION_VOLUME_STREAM = 210;
+
+ // ACTION: Adjust volume with hardware key
+ // SUBTYPE: volume level (0-7)
+ // CATEGORY: GLOBAL_SYSTEM_UI
+ // OS: 6.0
+ // GMS: 7.5.26
ACTION_VOLUME_KEY = 211;
+
+ // ACTION: Volume dialog > Mute a stream by tapping icon
+ // SUBTYPE: mute is 1, audible is 2
+ // CATEGORY: GLOBAL_SYSTEM_UI
+ // OS: 6.0
+ // GMS: 7.5.26
ACTION_VOLUME_ICON = 212;
+
+ // ACTION: Volume dialog > Change ringer mode by tapping icon
+ // SUBTYPE: 2 is audible, 3 is vibrate
+ // CATEGORY: GLOBAL_SYSTEM_UI
+ // OS: 6.0
+ // GMS: 7.5.26
ACTION_RINGER_MODE = 213;
+
+ // ACTION: Chooser shown (share target, file open, etc.)
+ // CATEGORY: GLOBAL_SYSTEM_UI
+ // OS: 6.0
+ // GMS: 7.5.26
ACTION_ACTIVITY_CHOOSER_SHOWN = 214;
+
+ // ACTION: Chooser > User taps an app target
+ // SUBTYPE: Index of target
+ // CATEGORY: GLOBAL_SYSTEM_UI
+ // OS: 6.0
+ // GMS: 7.5.26
ACTION_ACTIVITY_CHOOSER_PICKED_APP_TARGET = 215;
+
+ // ACTION: Chooser > User taps a service target
+ // SUBTYPE: Index of target
+ // CATEGORY: GLOBAL_SYSTEM_UI
+ // OS: 6.0
+ // GMS: 7.5.26
ACTION_ACTIVITY_CHOOSER_PICKED_SERVICE_TARGET = 216;
+
+ // ACTION: Chooser > User taps a standard target
+ // SUBTYPE: Index of target
+ // CATEGORY: GLOBAL_SYSTEM_UI
+ // OS: 6.0
+ // GMS: 7.5.26
ACTION_ACTIVITY_CHOOSER_PICKED_STANDARD_TARGET = 217;
+
+ // ACTION: QS Brightness Slider (with auto brightness disabled)
+ // SUBTYPE: slider value
+ // CATEGORY: QUICK_SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
ACTION_BRIGHTNESS = 218;
+
+ // ACTION: QS Brightness Slider (with auto brightness enabled)
+ // SUBTYPE: slider value
+ // CATEGORY: QUICK_SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
ACTION_BRIGHTNESS_AUTO = 219;
+
+ // OPEN: Settings > Display > Brightness Slider
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
BRIGHTNESS_DIALOG = 220;
+
+ // OPEN: Settings > Apps > Configure Apps > Draw over other apps
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
SYSTEM_ALERT_WINDOW_APPS = 221;
+
+ // OPEN: Display has entered dream mode
+ // CATEGORY: GLOBAL_SYSTEM_UI
+ // OS: 6.0
+ // GMS: 7.5.26
DREAMING = 222;
+
+ // OPEN: Display has entered ambient notification mode
+ // CATEGORY: GLOBAL_SYSTEM_UI
+ // OS: 6.0
+ // GMS: 7.5.26
DOZING = 223;
+
+ // OPEN: Overview
+ // CATEGORY: GLOBAL_SYSTEM_UI
+ // OS: 6.0
+ // GMS: 7.5.26
OVERVIEW_ACTIVITY = 224;
+
+ // OPEN: Settings > About phone > Legal information
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
ABOUT_LEGAL_SETTINGS = 225;
+
+ // OPEN: Settings > Search > Perform search
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
ACTION_SEARCH_RESULTS = 226;
+
+ // OPEN: Settings > System UI Tuner
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
TUNER = 227;
+
+ // OPEN: Settings > System UI Tuner > Quick Settings
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
TUNER_QS = 228;
+
+ // OPEN: Settings > System UI Tuner > Demo mode
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
TUNER_DEMO_MODE = 229;
+
+ // ACTION: Settings > System UI Tuner > Quick Settings > Move tile
+ // PACKAGE: Tile
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
TUNER_QS_REORDER = 230;
+
+ // ACTION: Settings > System UI Tuner > Quick Settings > Add tile
+ // PACKAGE: Tile
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
TUNER_QS_ADD = 231;
+
+ // ACTION: Settings > System UI Tuner > Quick Settings > Remove tile
+ // PACKAGE: Tile
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
TUNER_QS_REMOVE = 232;
+
+ // ACTION: Settings > System UI Tuner > Status bar > Enable icon
+ // PACKAGE: Icon
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
TUNER_STATUS_BAR_ENABLE = 233;
+
+ // ACTION: Settings > System UI Tuner > Status bar > Disable icon
+ // PACKAGE: Icon
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
TUNER_STATUS_BAR_DISABLE = 234;
+
+ // ACTION: Settings > System UI Tuner > Demo mode > Enable demo mode
+ // SUBTYPE: false is disabled, true is enabled
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
TUNER_DEMO_MODE_ENABLED = 235;
+
+ // ACTION: Settings > System UI Tuner > Demo mode > Show demo mode
+ // SUBTYPE: false is disabled, true is enabled
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
TUNER_DEMO_MODE_ON = 236;
+
+ // ACTION: Settings > System UI Tuner > Show embedded battery percentage
+ // SUBTYPE: 0 is disabled, 1 is enabled
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
TUNER_BATTERY_PERCENTAGE = 237;
+
+ // OPEN: Settings > Developer options > Inactive apps
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.5.26
FUELGAUGE_INACTIVE_APPS = 238;
+
+ // ACTION: Long press home to bring up assistant
+ // CATEGORY: GLOBAL_SYSTEM_UI
+ // OS: 6.0
+ // GMS: 7.5.26
ACTION_ASSIST_LONG_PRESS = 239;
+
+ // OPEN: Settings > Security > Nexus Imprint > Add Fingerprint
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.8.99
FINGERPRINT_ENROLLING = 240;
+
+ // OPEN: Fingerprint Enroll > Find Sensor
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.8.99
FINGERPRINT_FIND_SENSOR = 241;
+
+ // OPEN: Fingerprint Enroll > Fingerprint Enrolled!
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.8.99
FINGERPRINT_ENROLL_FINISH = 242;
+
+ // OPEN: Fingerprint Enroll introduction
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.8.99
FINGERPRINT_ENROLL_INTRO = 243;
+
+ // OPEN: Fingerprint Enroll onboarding
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.8.99
FINGERPRINT_ENROLL_ONBOARD = 244;
+
+ // OPEN: Fingerprint Enroll > Let's Start!
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.8.99
FINGERPRINT_ENROLL_SIDECAR = 245;
+
+ // OPEN: Fingerprint Enroll SUW > Let's Start!
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.8.99
FINGERPRINT_ENROLLING_SETUP = 246;
+
+ // OPEN: Fingerprint Enroll SUW > Find Sensor
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.8.99
FINGERPRINT_FIND_SENSOR_SETUP = 247;
+
+ // OPEN: Fingerprint Enroll SUW > Fingerprint Enrolled!
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.8.99
FINGERPRINT_ENROLL_FINISH_SETUP = 248;
+
+ // OPEN: Fingerprint Enroll SUW introduction
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.8.99
FINGERPRINT_ENROLL_INTRO_SETUP = 249;
+
+ // OPEN: Fingerprint Enroll SUW onboarding
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.8.99
FINGERPRINT_ENROLL_ONBOARD_SETUP = 250;
+
+ // ACTION: Add fingerprint > Enroll fingerprint
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.8.99
ACTION_FINGERPRINT_ENROLL = 251;
+
+ // ACTION: Authenticate using fingerprint
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.8.99
ACTION_FINGERPRINT_AUTH = 252;
+
+ // ACTION: Settings > Security > Nexus Imprint > [Fingerprint] > Delete
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.8.99
ACTION_FINGERPRINT_DELETE = 253;
+
+ // ACTION: Settings > Security > Nexus Imprint > [Fingerprint] > Rename
+ // CATEGORY: SETTINGS
+ // OS: 6.0
+ // GMS: 7.8.99
ACTION_FINGERPRINT_RENAME = 254;
+
+ // ACTION: Double tap camera shortcut
+ // CATEGORY: GLOBAL_SYSTEM_UI
+ // OS: 6.0
+ // GMS: 7.8.99
ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE = 255;
+
+ // ACTION: Double twist camera shortcut
+ // CATEGORY: GLOBAL_SYSTEM_UI
+ // OS: 6.0
+ // GMS: 7.8.99
ACTION_WIGGLE_CAMERA_GESTURE = 256;
+
+ // OPEN: QS Work Mode tile shown
+ // ACTION: QS Work Mode tile tapped
+ // SUBTYPE: 0 is off, 1 is on
+ // CATEGORY: QUICK_SETTINGS
+ // OS: N
+ // GMS: 7.8.99
QS_WORKMODE = 257;
+
+ // OPEN: Settings > Developer Options > Background Check
+ // CATEGORY: SETTINGS
+ // OS: N
+ // GMS: 7.8.99
BACKGROUND_CHECK_SUMMARY = 258;
+
+ // OPEN: QS Lock tile shown
+ // ACTION: QS Lock tile tapped
+ // SUBTYPE: 0 is off, 1 is on
+ // CATEGORY: QUICK_SETTINGS
+ // OS: N
+ // GMS: 7.8.99
QS_LOCK_TILE = 259;
+
+ // OPEN: QS User Tile shown
+ // CATEGORY: QUICK_SETTINGS
+ // OS: N
+ // GMS: 7.8.99
QS_USER_TILE = 260;
+
+ // OPEN: QS Battery tile shown
+ // CATEGORY: QUICK_SETTINGS
+ // OS: N
+ // GMS: 7.8.99
QS_BATTERY_TILE = 261;
+
+ // OPEN: Settings > Sound > Do not disturb > Visual interruptions
+ // CATEGORY: SETTINGS
+ // OS: N
+ // GMS: 7.8.99
NOTIFICATION_ZEN_MODE_VISUAL_INTERRUPTIONS = 262;
+
+ // ACTION: Visual interruptions > No screen interuptions toggle
+ // SUBTYPE: 0 is off, 1 is on
+ // CATEGORY: SETTINGS
+ // OS: N
+ // GMS: 7.8.99
ACTION_ZEN_ALLOW_WHEN_SCREEN_OFF = 263;
- // Dead
+
+ // ACTION: Visual interruptions > No notification light toggle
+ // SUBTYPE: 0 is off, 1 is on
+ // CATEGORY: SETTINGS
+ // OS: N
+ // GMS: 7.8.99
ACTION_ZEN_ALLOW_LIGHTS = 264;
+
+ // OPEN: Settings > Notifications > [App] > Topic Notifications
+ // CATEGORY: SETTINGS
+ // OS: N
+ // GMS: 7.8.99
NOTIFICATION_TOPIC_NOTIFICATION = 265;
+
+ // ACTION: Settings > Apps > Default Apps > Select different SMS app
+ // PACKAGE: Selected SMS app
+ // CATEGORY: SETTINGS
+ // OS: N
+ // GMS: 7.8.99
ACTION_DEFAULT_SMS_APP_CHANGED = 266;
+
+ // OPEN: QS Color modification tile shown
+ // ACTION: QS Color modification tile tapped
+ // SUBTYPE: 0 is off, 1 is on
+ // CATEGORY: QUICK_SETTINGS
+ // OS: N
+ // GMS: 7.8.99
QS_COLOR_MATRIX = 267;
+
+ // OPEN: QS Custom tile shown
+ // ACTION: QS Work Mode tile tapped
+ // CATEGORY: QUICK_SETTINGS
+ // OS: N
+ // GMS: 7.8.99
QS_CUSTOM = 268;
+
+ // ACTION: Visual interruptions > Never turn off the screen toggle
+ // SUBTYPE: 0 is off, 1 is on
+ // CATEGORY: SETTINGS
+ // OS: N
+ // GMS: 7.8.99
ACTION_ZEN_ALLOW_WHEN_SCREEN_ON = 269;
- // Logged when the user docks a window from recents by
- // longpressing a task and dragging it to the dock area.
+ // ACTION: Overview > Long-press task, drag to enter split-screen
+ // CATEGORY: GLOBAL_SYSTEM_UI
+ // OS: N
+ // GMS: 7.8.99
ACTION_WINDOW_DOCK_DRAG_DROP = 270;
- // Logged when the user docks a fullscreen window by long pressing
- // recents which also opens recents on the lower/right side.
+ // ACTION: In App > Long-press Overview button to enter split-screen
+ // CATEGORY: GLOBAL_SYSTEM_UI
+ // OS: N
+ // GMS: 7.8.99
ACTION_WINDOW_DOCK_LONGPRESS = 271;
- // Logged when the user docks a window by dragging from the navbar
- // which also opens recents on the lower/right side.
+ // ACTION: In App > Swipe Overview button to enter split-screen
+ // CATEGORY: GLOBAL_SYSTEM_UI
+ // OS: N
+ // GMS: 7.8.99
ACTION_WINDOW_DOCK_SWIPE = 272;
- // Logged when the user launches a profile-specific app and we
- // intercept it with the confirm credentials UI.
+ // ACTION: Launch profile-specific app > Confirm credentials
+ // CATEGORY: GLOBAL_SYSTEM_UI
+ // OS: N
+ // GMS: 7.8.99
PROFILE_CHALLENGE = 273;
+ // OPEN: QS Battery detail panel
+ // CATEGORY: GLOBAL_SYSTEM_UI
+ // OS: N
+ // GMS: 7.8.99
QS_BATTERY_DETAIL = 274;
- // Logged when the user goes into the overview history.
+ // OPEN: Overview > History
+ // CATEGORY: GLOBAL_SYSTEM_UI
+ // OS: N
+ // GMS: 7.8.99
OVERVIEW_HISTORY = 275;
- // Logged when the user pages through overview.
- OVERVIEW_PAGE = 276;
+ // ACTION: Overview > Page by tapping Overview button
+ // CATEGORY: GLOBAL_SYSTEM_UI
+ // OS: N
+ // GMS: 7.8.99
+ ACTION_OVERVIEW_PAGE = 276;
- // Logged when the user launches a task from overview.
- OVERVIEW_SELECT = 277;
+ // ACTION: Overview > Select app
+ // CATEGORY: GLOBAL_SYSTEM_UI
+ // OS: N
+ // GMS: 7.8.99
+ ACTION_OVERVIEW_SELECT = 277;
- // Logged when the user views the emergency info.
+ // ACTION: View emergency info
+ // CATEGORY: GLOBAL_SYSTEM_UI
+ // OS: N
+ // GMS: 7.8.99
ACTION_VIEW_EMERGENCY_INFO = 278;
- // Logged when the user views the edit emergency info activity.
+ // ACTION: Edit emergency info activity
+ // CATEGORY: SETTINGS
+ // OS: N
+ // GMS: 7.8.99
ACTION_EDIT_EMERGENCY_INFO = 279;
- // Logged when the user edits an emergency info field.
+ // ACTION: Edit emergency info field
+ // CATEGORY: SETTINGS
+ // OS: N
+ // GMS: 7.8.99
ACTION_EDIT_EMERGENCY_INFO_FIELD = 280;
- // Logged when the user adds a new emergency contact.
+ // ACTION: Add emergency contact
+ // CATEGORY: SETTINGS
+ // OS: N
+ // GMS: 7.8.99
ACTION_ADD_EMERGENCY_CONTACT = 281;
- // Logged when the user deletes an emergency contact.
+ // ACTION: Delete emergency contact
+ // CATEGORY: SETTINGS
+ // OS: N
+ // GMS: 7.8.99
ACTION_DELETE_EMERGENCY_CONTACT = 282;
- // Logged when the user calls an emergency contact.
+ // ACTION: Call emergency contact
+ // CATEGORY: SETTINGS
+ // OS: N
+ // GMS: 7.8.99
ACTION_CALL_EMERGENCY_CONTACT = 283;
- // QS Tile for Data Saver.
+ // OPEN: QS Data Saver tile shown
+ // ACTION: QS Data Saver tile tapped
+ // CATEGORY: QUICK_SETTINGS
QS_DATA_SAVER = 284;
// OPEN: Settings > Security > User credentials
// CATEGORY: Settings
- // OS: 6.1
+ // OS: N
// GMS: 7.8.99
USER_CREDENTIALS = 285;
- // Logged when the user undocks a previously docked window by long pressing recents while in
- // docked mode.
+ // ACTION: In App (splitscreen) > Long-press Overview to exit split-screen
+ // CATEGORY: GLOBAL_SYSTEM_UI
+ // OS: N
+ // GMS: 7.8.99
ACTION_WINDOW_UNDOCK_LONGPRESS = 286;
// Logged when the user scrolls through overview manually
@@ -370,43 +1770,66 @@
// indicate the user lowered the importance; positive means they increased it.
ACTION_SAVE_IMPORTANCE = 291;
- // Interactive bug report initiated from power menu.
+ // ACTION: Long-press power button, then tap "Take bug report" option.
+ // CATEGORY: GLOBAL_SYSTEM_UI
+ // OS: N
+ // GMS: 7.8.99
ACTION_BUGREPORT_FROM_POWER_MENU_INTERACTIVE = 292;
- // Full bug report initiated from power menu.
+ // ACTION: Long-press power button, then long-press "Take bug report" option.
+ // CATEGORY: GLOBAL_SYSTEM_UI
+ // OS: N
+ // GMS: 7.8.99
ACTION_BUGREPORT_FROM_POWER_MENU_FULL = 293;
+ // ACTION: Settings -> Developer Options -> Take bug report -> Interactive report
+ // CATEGORY: SETTINGS
+ // OS: N
+ // GMS: 7.8.99
// Interactive bug report initiated from Settings.
ACTION_BUGREPORT_FROM_SETTINGS_INTERACTIVE = 294;
- // Full bug report initiated from Settings.
+ // ACTION: Settings -> Developer Options -> Take bug report -> Full report
+ // CATEGORY: SETTINGS
+ // OS: N
+ // GMS: 7.8.99
+ // Interactive bug report initiated from Settings.
ACTION_BUGREPORT_FROM_SETTINGS_FULL = 295;
- // Bug report canceled using system notification.
+ // ACTION: User tapped notification action to cancel a bug report
+ // CATEGORY: NOTIFICATION
ACTION_BUGREPORT_NOTIFICATION_ACTION_CANCEL = 296;
- // Bug report details screen open using system notification.
+ // ACTION: User tapped notification action to launch bug report details screen
+ // CATEGORY: NOTIFICATION
ACTION_BUGREPORT_NOTIFICATION_ACTION_DETAILS = 297;
- // Additional Bug report screen shot taken using system notification.
+ // ACTION: User tapped notification action to take adition screenshot on bug report
+ // CATEGORY: NOTIFICATION
ACTION_BUGREPORT_NOTIFICATION_ACTION_SCREENSHOT = 298;
- // Bug report shared by user using system notification.
+ // ACTION: User tapped notification to share bug report
+ // CATEGORY: NOTIFICATION
ACTION_BUGREPORT_NOTIFICATION_ACTION_SHARE = 299;
- // User changed bug report name using the details screen.
+ // ACTION: User changed bug report name using the details screen
+ // CATEGORY: GLOBAL_SYSTEM_UI
ACTION_BUGREPORT_DETAILS_NAME_CHANGED = 300;
- // User changed bug report title using the details screen.
+ // ACTION: User changed bug report title using the details screen
+ // CATEGORY: GLOBAL_SYSTEM_UI
ACTION_BUGREPORT_DETAILS_TITLE_CHANGED = 301;
- // User changed bug report description using the details screen.
+ // ACTION: User changed bug report description using the details screen
+ // CATEGORY: GLOBAL_SYSTEM_UI
ACTION_BUGREPORT_DETAILS_DESCRIPTION_CHANGED = 302;
- // Changes made on bug report details screen were saved by user.
+ // ACTION: User tapped Save in the bug report details screen.
+ // CATEGORY: GLOBAL_SYSTEM_UI
ACTION_BUGREPORT_DETAILS_SAVED = 303;
- // Changes made on bug report details screen were canceled by user.
+ // ACTION: User tapped Cancel in the bug report details screen.
+ // CATEGORY: GLOBAL_SYSTEM_UI
ACTION_BUGREPORT_DETAILS_CANCELED = 304;
// Tuner: Open/close calibrate dialog.
@@ -504,6 +1927,14 @@
// access before; action pass package name of calling package.
ACTION_SCOPED_DIRECTORY_ACCESS_ALREADY_GRANTED_BY_PACKAGE = 331;
+ // Logged when the user slides a notification and
+ // reveals the gear beneath it.
+ ACTION_REVEAL_GEAR = 332;
+
+ // Logged when the user taps on the gear beneath
+ // a notification.
+ ACTION_TOUCH_GEAR = 333;
+
// Add new aosp constants above this line.
// END OF AOSP CONSTANTS
diff --git a/rs/java/android/renderscript/Allocation.java b/rs/java/android/renderscript/Allocation.java
index 8c78a3a..fc92966 100644
--- a/rs/java/android/renderscript/Allocation.java
+++ b/rs/java/android/renderscript/Allocation.java
@@ -115,7 +115,7 @@
if (cmp == Short.TYPE) {
if (checkType) {
- validateIsInt16();
+ validateIsInt16OrFloat16();
return mType.mElement.mType;
}
return Element.DataType.SIGNED_16;
@@ -402,9 +402,10 @@
"32 bit integer source does not match allocation type " + mType.mElement.mType);
}
- private void validateIsInt16() {
+ private void validateIsInt16OrFloat16() {
if ((mType.mElement.mType == Element.DataType.SIGNED_16) ||
- (mType.mElement.mType == Element.DataType.UNSIGNED_16)) {
+ (mType.mElement.mType == Element.DataType.UNSIGNED_16) ||
+ (mType.mElement.mType == Element.DataType.FLOAT_16)) {
return;
}
throw new RSIllegalArgumentException(
@@ -751,7 +752,7 @@
* @param d the source data array
*/
public void copyFrom(short[] d) {
- validateIsInt16();
+ validateIsInt16OrFloat16();
copyFromUnchecked(d, Element.DataType.SIGNED_16, d.length);
}
@@ -1060,7 +1061,7 @@
* @param d the source data array
*/
public void copy1DRangeFrom(int off, int count, short[] d) {
- validateIsInt16();
+ validateIsInt16OrFloat16();
copy1DRangeFromUnchecked(off, count, d, Element.DataType.SIGNED_16, d.length);
}
@@ -1204,7 +1205,7 @@
* @param data to be placed into the Allocation
*/
public void copy2DRangeFrom(int xoff, int yoff, int w, int h, short[] data) {
- validateIsInt16();
+ validateIsInt16OrFloat16();
copy2DRangeFromUnchecked(xoff, yoff, w, h, data,
Element.DataType.SIGNED_16, data.length);
}
@@ -1473,7 +1474,7 @@
* @param d The array to be set from the Allocation.
*/
public void copyTo(short[] d) {
- validateIsInt16();
+ validateIsInt16OrFloat16();
copyTo(d, Element.DataType.SIGNED_16, d.length);
}
@@ -1693,7 +1694,7 @@
* @param d the source data array
*/
public void copy1DRangeTo(int off, int count, short[] d) {
- validateIsInt16();
+ validateIsInt16OrFloat16();
copy1DRangeToUnchecked(off, count, d, Element.DataType.SIGNED_16, d.length);
}
@@ -1794,7 +1795,7 @@
* @param data Dest Array to be copied into
*/
public void copy2DRangeTo(int xoff, int yoff, int w, int h, short[] data) {
- validateIsInt16();
+ validateIsInt16OrFloat16();
copy2DRangeToUnchecked(xoff, yoff, w, h, data,
Element.DataType.SIGNED_16, data.length);
}
diff --git a/rs/jni/android_renderscript_RenderScript.cpp b/rs/jni/android_renderscript_RenderScript.cpp
index 3bef19e..4877a378 100644
--- a/rs/jni/android_renderscript_RenderScript.cpp
+++ b/rs/jni/android_renderscript_RenderScript.cpp
@@ -151,6 +151,7 @@
return; \
case RS_TYPE_SIGNED_16: \
case RS_TYPE_UNSIGNED_16: \
+ case RS_TYPE_FLOAT_16: \
len = _env->GetArrayLength((jshortArray)data); \
ptr = _env->GetShortArrayElements((jshortArray)data, flag); \
if (ptr == nullptr) { \
@@ -1061,7 +1062,7 @@
type, kind, norm, size);
}
return (jlong)(uintptr_t)rsElementCreate((RsContext)con, (RsDataType)type, (RsDataKind)kind,
- norm, size);
+ norm, size, true);
}
static jlong
@@ -1100,7 +1101,7 @@
jlong id = (jlong)(uintptr_t)rsElementCreate2((RsContext)con,
(const RsElement *)ids, fieldCount,
nameArray, fieldCount * sizeof(size_t), sizeArray,
- (const uint32_t *)arraySizes, fieldCount);
+ (const uint32_t *)arraySizes, fieldCount, true);
free(ids);
free(arraySizes);
@@ -1174,7 +1175,7 @@
}
return (jlong)(uintptr_t)rsTypeCreate((RsContext)con, (RsElement)eid, dimx, dimy, dimz, mips,
- faces, yuv);
+ faces, yuv, true);
}
static void
@@ -1210,7 +1211,7 @@
}
return (jlong)(uintptr_t) rsAllocationCreateTyped((RsContext)con, (RsType)type,
(RsAllocationMipmapControl)mips,
- (uint32_t)usage, (uintptr_t)pointer);
+ (uint32_t)usage, (uintptr_t)pointer, true);
}
static void
@@ -1315,7 +1316,7 @@
const void* ptr = bitmap.getPixels();
jlong id = (jlong)(uintptr_t)rsAllocationCreateFromBitmap((RsContext)con,
(RsType)type, (RsAllocationMipmapControl)mip,
- ptr, bitmap.getSize(), usage);
+ ptr, bitmap.getSize(), usage, true);
bitmap.unlockPixels();
return id;
}
@@ -1331,7 +1332,7 @@
const void* ptr = bitmap.getPixels();
jlong id = (jlong)(uintptr_t)rsAllocationCreateTyped((RsContext)con,
(RsType)type, (RsAllocationMipmapControl)mip,
- (uint32_t)usage, (uintptr_t)ptr);
+ (uint32_t)usage, (uintptr_t)ptr, true);
bitmap.unlockPixels();
return id;
}
@@ -1347,7 +1348,7 @@
const void* ptr = bitmap.getPixels();
jlong id = (jlong)(uintptr_t)rsAllocationCubeCreateFromBitmap((RsContext)con,
(RsType)type, (RsAllocationMipmapControl)mip,
- ptr, bitmap.getSize(), usage);
+ ptr, bitmap.getSize(), usage, true);
bitmap.unlockPixels();
return id;
}
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index acd57b17..9e6c21c 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -655,10 +655,9 @@
userState.mUiAutomationServiceOwner = owner;
userState.mUiAutomationServiceClient = serviceClient;
userState.mUiAutomationFlags = flags;
- userState.mIsAccessibilityEnabled = true;
userState.mInstalledServices.add(accessibilityServiceInfo);
if ((flags & UiAutomation.FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES) == 0) {
- // Set the temporary state.
+ // Set the temporary state, and use it instead of settings
userState.mIsTouchExplorationEnabled = false;
userState.mIsEnhancedWebAccessibilityEnabled = false;
userState.mIsDisplayMagnificationEnabled = false;
@@ -709,7 +708,6 @@
return;
}
- userState.mIsAccessibilityEnabled = true;
userState.mIsTouchExplorationEnabled = touchExplorationEnabled;
userState.mIsEnhancedWebAccessibilityEnabled = false;
userState.mIsDisplayMagnificationEnabled = false;
@@ -1245,17 +1243,17 @@
}
}
- private void manageServicesLocked(UserState userState) {
+ private void updateServicesLocked(UserState userState) {
Map<ComponentName, Service> componentNameToServiceMap =
userState.mComponentNameToServiceMap;
boolean isUnlocked = mContext.getSystemService(UserManager.class)
.isUserUnlocked(userState.mUserId);
- boolean isEnabled = userState.mIsAccessibilityEnabled;
for (int i = 0, count = userState.mInstalledServices.size(); i < count; i++) {
AccessibilityServiceInfo installedService = userState.mInstalledServices.get(i);
ComponentName componentName = ComponentName.unflattenFromString(
installedService.getId());
+
Service service = componentNameToServiceMap.get(componentName);
// Ignore non-encryption-aware services until user is unlocked
@@ -1264,45 +1262,25 @@
continue;
}
- if (isEnabled) {
- // Wait for the binding if it is in process.
- if (userState.mBindingServices.contains(componentName)) {
+ // Wait for the binding if it is in process.
+ if (userState.mBindingServices.contains(componentName)) {
+ continue;
+ }
+ if (userState.mEnabledServices.contains(componentName)) {
+ if (service == null) {
+ service = new Service(userState.mUserId, componentName, installedService);
+ } else if (userState.mBoundServices.contains(service)) {
continue;
}
- if (userState.mEnabledServices.contains(componentName)) {
- if (service == null) {
- service = new Service(userState.mUserId, componentName, installedService);
- } else if (userState.mBoundServices.contains(service)) {
- continue;
- }
- service.bindLocked();
- } else {
- if (service != null) {
- service.unbindLocked();
- }
- }
+ service.bindLocked();
} else {
if (service != null) {
service.unbindLocked();
- } else {
- userState.mBindingServices.remove(componentName);
}
}
}
- // No enabled installed services => disable accessibility to avoid
- // sending accessibility events with no recipient across processes.
- if (isEnabled && isUnlocked && userState.mBoundServices.isEmpty()
- && userState.mBindingServices.isEmpty()) {
- userState.mIsAccessibilityEnabled = false;
- final long identity = Binder.clearCallingIdentity();
- try {
- Settings.Secure.putIntForUser(mContext.getContentResolver(),
- Settings.Secure.ACCESSIBILITY_ENABLED, 0, userState.mUserId);
- } finally {
- Binder.restoreCallingIdentity(identity);
- }
- }
+ updateAccessibilityEnabledSetting(userState);
}
private void scheduleUpdateClientsIfNeededLocked(UserState userState) {
@@ -1329,7 +1307,8 @@
flags |= AccessibilityInputFilter.FLAG_FEATURE_SCREEN_MAGNIFIER;
}
// Touch exploration without accessibility makes no sense.
- if (userState.mIsAccessibilityEnabled && userState.mIsTouchExplorationEnabled) {
+ if (userState.isHandlingAccessibilityEvents()
+ && userState.mIsTouchExplorationEnabled) {
flags |= AccessibilityInputFilter.FLAG_FEATURE_TOUCH_EXPLORATION;
}
if (userState.mIsFilterKeyEventsEnabled) {
@@ -1468,25 +1447,17 @@
}
private void updateWindowsForAccessibilityCallbackLocked(UserState userState) {
- if (userState.mIsAccessibilityEnabled) {
- // We observe windows for accessibility only if there is at least
- // one bound service that can retrieve window content that specified
- // it is interested in accessing such windows. For services that are
- // binding we do an update pass after each bind event, so we run this
- // code and register the callback if needed.
- boolean boundServiceCanRetrieveInteractiveWindows = false;
+ // We observe windows for accessibility only if there is at least
+ // one bound service that can retrieve window content that specified
+ // it is interested in accessing such windows. For services that are
+ // binding we do an update pass after each bind event, so we run this
+ // code and register the callback if needed.
- List<Service> boundServices = userState.mBoundServices;
- final int boundServiceCount = boundServices.size();
- for (int i = 0; i < boundServiceCount; i++) {
- Service boundService = boundServices.get(i);
- if (boundService.canRetrieveInteractiveWindowsLocked()) {
- boundServiceCanRetrieveInteractiveWindows = true;
- break;
- }
- }
-
- if (boundServiceCanRetrieveInteractiveWindows) {
+ List<Service> boundServices = userState.mBoundServices;
+ final int boundServiceCount = boundServices.size();
+ for (int i = 0; i < boundServiceCount; i++) {
+ Service boundService = boundServices.get(i);
+ if (boundService.canRetrieveInteractiveWindowsLocked()) {
if (mWindowsForAccessibilityCallback == null) {
mWindowsForAccessibilityCallback = new WindowsForAccessibilityCallback();
mWindowManagerService.setWindowsForAccessibilityCallback(
@@ -1554,37 +1525,30 @@
userState.mIsFilterKeyEventsEnabled = false;
}
- private void updateServicesLocked(UserState userState) {
- if (userState.mIsAccessibilityEnabled) {
- manageServicesLocked(userState);
- } else {
- unbindAllServicesLocked(userState);
- }
- }
-
private boolean readConfigurationForUserStateLocked(UserState userState) {
- boolean somthingChanged = readAccessibilityEnabledSettingLocked(userState);
- somthingChanged |= readInstalledAccessibilityServiceLocked(userState);
- somthingChanged |= readEnabledAccessibilityServicesLocked(userState);
- somthingChanged |= readTouchExplorationGrantedAccessibilityServicesLocked(userState);
- somthingChanged |= readTouchExplorationEnabledSettingLocked(userState);
- somthingChanged |= readHighTextContrastEnabledSettingLocked(userState);
- somthingChanged |= readEnhancedWebAccessibilityEnabledChangedLocked(userState);
- somthingChanged |= readDisplayMagnificationEnabledSettingLocked(userState);
- somthingChanged |= readAutoclickEnabledSettingLocked(userState);
- somthingChanged |= readDisplayColorAdjustmentSettingsLocked(userState);
- return somthingChanged;
+ boolean somethingChanged = readInstalledAccessibilityServiceLocked(userState);
+ somethingChanged |= readEnabledAccessibilityServicesLocked(userState);
+ somethingChanged |= readTouchExplorationGrantedAccessibilityServicesLocked(userState);
+ somethingChanged |= readTouchExplorationEnabledSettingLocked(userState);
+ somethingChanged |= readHighTextContrastEnabledSettingLocked(userState);
+ somethingChanged |= readEnhancedWebAccessibilityEnabledChangedLocked(userState);
+ somethingChanged |= readDisplayMagnificationEnabledSettingLocked(userState);
+ somethingChanged |= readAutoclickEnabledSettingLocked(userState);
+ somethingChanged |= readDisplayColorAdjustmentSettingsLocked(userState);
+
+ return somethingChanged;
}
- private boolean readAccessibilityEnabledSettingLocked(UserState userState) {
- final boolean accessibilityEnabled = Settings.Secure.getIntForUser(
- mContext.getContentResolver(),
- Settings.Secure.ACCESSIBILITY_ENABLED, 0, userState.mUserId) == 1;
- if (accessibilityEnabled != userState.mIsAccessibilityEnabled) {
- userState.mIsAccessibilityEnabled = accessibilityEnabled;
- return true;
+ private void updateAccessibilityEnabledSetting(UserState userState) {
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ Settings.Secure.putIntForUser(mContext.getContentResolver(),
+ Settings.Secure.ACCESSIBILITY_ENABLED,
+ userState.isHandlingAccessibilityEvents() ? 0 : 1,
+ userState.mUserId);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
}
- return false;
}
private boolean readTouchExplorationEnabledSettingLocked(UserState userState) {
@@ -1809,7 +1773,7 @@
// Check whether any Accessibility Services are still enabled and, if not, remove flag
// requesting no soft keyboard
final boolean accessibilityRequestingNoIme = userState.mSoftKeyboardShowMode == 1;
- if (accessibilityRequestingNoIme && !userState.mIsAccessibilityEnabled) {
+ if (accessibilityRequestingNoIme && !userState.isHandlingAccessibilityEvents()) {
// No active Accessibility Services can be requesting the soft keyboard to be hidden
Settings.Secure.putIntForUser(mContext.getContentResolver(),
Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE,
@@ -1853,7 +1817,6 @@
UserState userState = mUserStates.valueAt(i);
pw.append("User state[attributes:{id=" + userState.mUserId);
pw.append(", currentUser=" + (userState.mUserId == mCurrentUserId));
- pw.append(", accessibilityEnabled=" + userState.mIsAccessibilityEnabled);
pw.append(", touchExplorationEnabled=" + userState.mIsTouchExplorationEnabled);
pw.append(", displayMagnificationEnabled="
+ userState.mIsDisplayMagnificationEnabled);
@@ -2003,7 +1966,7 @@
private void announceNewUserIfNeeded() {
synchronized (mLock) {
UserState userState = getCurrentUserStateLocked();
- if (userState.mIsAccessibilityEnabled) {
+ if (userState.isHandlingAccessibilityEvents()) {
UserManager userManager = (UserManager) mContext.getSystemService(
Context.USER_SERVICE);
String message = mContext.getString(R.string.user_switched,
@@ -4061,7 +4024,6 @@
public int mSoftKeyboardShowMode = 0;
- public boolean mIsAccessibilityEnabled;
public boolean mIsTouchExplorationEnabled;
public boolean mIsTextHighContrastEnabled;
public boolean mIsEnhancedWebAccessibilityEnabled;
@@ -4096,11 +4058,11 @@
public int getClientState() {
int clientState = 0;
- if (mIsAccessibilityEnabled) {
+ if (isHandlingAccessibilityEvents()) {
clientState |= AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED;
}
// Touch exploration relies on enabled accessibility.
- if (mIsAccessibilityEnabled && mIsTouchExplorationEnabled) {
+ if (isHandlingAccessibilityEvents() && mIsTouchExplorationEnabled) {
clientState |= AccessibilityManager.STATE_FLAG_TOUCH_EXPLORATION_ENABLED;
}
if (mIsTextHighContrastEnabled) {
@@ -4109,6 +4071,10 @@
return clientState;
}
+ public boolean isHandlingAccessibilityEvents() {
+ return !mBoundServices.isEmpty() || !mBoundServices.isEmpty();
+ }
+
public void onSwitchToAnotherUser() {
// Clear UI test automation state.
if (mUiAutomationService != null) {
@@ -4128,7 +4094,6 @@
// Clear state persisted in settings.
mEnabledServices.clear();
mTouchExplorationGrantedServices.clear();
- mIsAccessibilityEnabled = false;
mIsTouchExplorationEnabled = false;
mIsEnhancedWebAccessibilityEnabled = false;
mIsDisplayMagnificationEnabled = false;
@@ -4155,9 +4120,6 @@
private final class AccessibilityContentObserver extends ContentObserver {
- private final Uri mAccessibilityEnabledUri = Settings.Secure.getUriFor(
- Settings.Secure.ACCESSIBILITY_ENABLED);
-
private final Uri mTouchExplorationEnabledUri = Settings.Secure.getUriFor(
Settings.Secure.TOUCH_EXPLORATION_ENABLED);
@@ -4199,8 +4161,6 @@
}
public void register(ContentResolver contentResolver) {
- contentResolver.registerContentObserver(mAccessibilityEnabledUri,
- false, this, UserHandle.USER_ALL);
contentResolver.registerContentObserver(mTouchExplorationEnabledUri,
false, this, UserHandle.USER_ALL);
contentResolver.registerContentObserver(mDisplayMagnificationEnabledUri,
@@ -4240,11 +4200,7 @@
return;
}
- if (mAccessibilityEnabledUri.equals(uri)) {
- if (readAccessibilityEnabledSettingLocked(userState)) {
- onUserStateChangedLocked(userState);
- }
- } else if (mTouchExplorationEnabledUri.equals(uri)) {
+ if (mTouchExplorationEnabledUri.equals(uri)) {
if (readTouchExplorationEnabledSettingLocked(userState)) {
onUserStateChangedLocked(userState);
}
diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
index f537d18..8603981 100644
--- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
+++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
@@ -16,9 +16,14 @@
package com.android.server.appwidget;
+import static android.content.Context.KEYGUARD_SERVICE;
+import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS;
+import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
+
import android.app.AlarmManager;
import android.app.AppGlobals;
import android.app.AppOpsManager;
+import android.app.KeyguardManager;
import android.app.PendingIntent;
import android.app.admin.DevicePolicyManagerInternal;
import android.app.admin.DevicePolicyManagerInternal.OnCrossProfileWidgetProvidersChangeListener;
@@ -72,10 +77,12 @@
import android.util.TypedValue;
import android.util.Xml;
import android.view.Display;
+import android.view.View;
import android.view.WindowManager;
import android.widget.RemoteViews;
import com.android.internal.R;
+import com.android.internal.app.UnlaunchableAppActivity;
import com.android.internal.appwidget.IAppWidgetHost;
import com.android.internal.appwidget.IAppWidgetService;
import com.android.internal.os.BackgroundThread;
@@ -146,7 +153,7 @@
final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL);
if (DEBUG) {
- Slog.i(TAG, "Received broadcast: " + action);
+ Slog.i(TAG, "Received broadcast: " + action + " on user " + userId);
}
if (Intent.ACTION_CONFIGURATION_CHANGED.equals(action)) {
@@ -156,10 +163,10 @@
} else if (Intent.ACTION_USER_STOPPED.equals(action)) {
onUserStopped(userId);
} else if (Intent.ACTION_USER_SWITCHED.equals(action)) {
- reloadWidgetsMaskedStateForUser(userId);
+ reloadWidgetsMaskedStateForGroup(userId);
} else if (Intent.ACTION_MANAGED_PROFILE_AVAILABILITY_CHANGED.equals(action)) {
synchronized (mLock) {
- reloadWidgetProfileUnavailableMaskedStateLocked(userId);
+ reloadWidgetsMaskedState(userId);
}
} else if (Intent.ACTION_PACKAGES_SUSPENDED.equals(action)) {
String[] packages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
@@ -202,6 +209,7 @@
private final AlarmManager mAlarmManager;
private final UserManager mUserManager;
private final AppOpsManager mAppOpsManager;
+ private final KeyguardManager mKeyguardManager;
private final SecurityPolicy mSecurityPolicy;
@@ -223,6 +231,7 @@
mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
mAppOpsManager = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
+ mKeyguardManager = (KeyguardManager) mContext.getSystemService(KEYGUARD_SERVICE);
mSaveStateHandler = BackgroundThread.getHandler();
mCallbackHandler = new CallbackHandler(mContext.getMainLooper());
mBackupRestoreController = new BackupRestoreController();
@@ -436,48 +445,51 @@
/**
* Reload all widgets' masked state for the given user and its associated profiles, including
* due to user not being available and package suspension.
+ * userId must be the group parent.
*/
- private void reloadWidgetsMaskedStateForUser(int userId) {
- if (!mUserManager.isUserUnlocked(userId) ||
- isProfileWithLockedParent(userId)) {
+ private void reloadWidgetsMaskedStateForGroup(int userId) {
+ if (!mUserManager.isUserUnlocked(userId)) {
return;
}
synchronized (mLock) {
- reloadWidgetPackageSuspensionMaskedStateLocked(userId);
+ reloadWidgetsMaskedState(userId);
List<UserInfo> profiles = mUserManager.getEnabledProfiles(userId);
if (profiles != null) {
for (int i = 0; i < profiles.size(); i++) {
UserInfo user = profiles.get(i);
- reloadWidgetProfileUnavailableMaskedStateLocked(user.id);
- reloadWidgetPackageSuspensionMaskedStateLocked(user.id);
+ reloadWidgetsMaskedState(user.id);
}
}
}
}
- /**
- * Mask/unmask widgets in the given profile, depending on the quiet state
- * or locked state of the profile.
- */
- private void reloadWidgetProfileUnavailableMaskedStateLocked(int profileId) {
+ private void reloadWidgetsMaskedState(int userId) {
final long identity = Binder.clearCallingIdentity();
try {
- if (!isProfileWithUnlockedParent(profileId)) {
- return;
- }
- UserInfo user = mUserManager.getUserInfo(profileId);
- boolean shouldMask = user.isQuietModeEnabled() ||
- !mUserManager.isUserUnlocked(user.getUserHandle());
+ UserInfo user = mUserManager.getUserInfo(userId);
+
+ boolean lockedProfile = !mUserManager.isUserUnlocked(userId);
+ boolean quietProfile = user.isQuietModeEnabled();
final int N = mProviders.size();
for (int i = 0; i < N; i++) {
Provider provider = mProviders.get(i);
int providerUserId = provider.getUserId();
- if (providerUserId != profileId) {
+ if (providerUserId != userId) {
continue;
}
- if (provider.setMaskedByProfileUnavailabledLocked(shouldMask)) {
+
+ boolean changed = provider.setMaskedByLockedProfileLocked(lockedProfile);
+ changed |= provider.setMaskedByQuietProfileLocked(quietProfile);
+ try {
+ boolean suspended = mPackageManager.isPackageSuspendedForUser(
+ provider.info.provider.getPackageName(), provider.getUserId());
+ changed |= provider.setMaskedBySuspendedPackageLocked(suspended);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Failed to query application info", e);
+ }
+ if (changed) {
if (provider.isMaskedLocked()) {
- maskWidgetsViewsLocked(provider);
+ maskWidgetsViewsLocked(provider, null);
} else {
unmaskWidgetsViewsLocked(provider);
}
@@ -489,33 +501,6 @@
}
/**
- * Reload widget's masked state due to package suspension state.
- */
- private void reloadWidgetPackageSuspensionMaskedStateLocked(int profileId) {
- final int N = mProviders.size();
- for (int i = 0; i < N; i++) {
- Provider provider = mProviders.get(i);
- int providerUserId = provider.getUserId();
- if (providerUserId != profileId) {
- continue;
- }
- try {
- boolean suspended = mPackageManager.isPackageSuspendedForUser(
- provider.info.provider.getPackageName(), provider.getUserId());
- if (provider.setMaskedBySuspendedPackageLocked(suspended)) {
- if (provider.isMaskedLocked()) {
- maskWidgetsViewsLocked(provider);
- } else {
- unmaskWidgetsViewsLocked(provider);
- }
- }
- } catch (RemoteException e) {
- Slog.e(TAG, "Failed to query application info", e);
- }
- }
- }
-
- /**
* Incrementally update the masked state due to package suspension state.
*/
private void updateWidgetPackageSuspensionMaskedState(String[] packagesArray, boolean suspended,
@@ -535,7 +520,7 @@
}
if (provider.setMaskedBySuspendedPackageLocked(suspended)) {
if (provider.isMaskedLocked()) {
- maskWidgetsViewsLocked(provider);
+ maskWidgetsViewsLocked(provider, null);
} else {
unmaskWidgetsViewsLocked(provider);
}
@@ -544,14 +529,13 @@
}
}
- private Bitmap createMaskedWidgetBitmap(Provider provider) {
+ private Bitmap createMaskedWidgetBitmap(String providerPackage, int providerUserId) {
final long identity = Binder.clearCallingIdentity();
try {
// Load the unbadged application icon and pass it to the widget to appear on
// the masked view.
- final String providerPackage = provider.info.provider.getPackageName();
Context userContext = mContext.createPackageContextAsUser(providerPackage, 0,
- UserHandle.of(provider.getUserId()));
+ UserHandle.of(providerUserId));
PackageManager pm = userContext.getPackageManager();
Drawable icon = pm.getApplicationInfo(providerPackage, 0).loadUnbadgedIcon(pm);
// Create a bitmap of the icon which is what the widget's remoteview requires.
@@ -566,18 +550,73 @@
}
}
- private void maskWidgetsViewsLocked(Provider provider) {
- Bitmap iconBitmap = createMaskedWidgetBitmap(provider);
+ private RemoteViews createMaskedWidgetRemoteViews(Bitmap icon, boolean showBadge,
+ PendingIntent onClickIntent) {
+ RemoteViews views = new RemoteViews(mContext.getPackageName(),
+ R.layout.work_widget_mask_view);
+ if (icon != null) {
+ views.setImageViewBitmap(R.id.work_widget_app_icon, icon);
+ }
+ if (!showBadge) {
+ views.setViewVisibility(R.id.work_widget_badge_icon, View.INVISIBLE);
+ }
+ if (onClickIntent != null) {
+ views.setOnClickPendingIntent(R.id.work_widget_mask_frame, onClickIntent);
+ }
+ return views;
+ }
+
+ /**
+ * Mask the target widget belonging to the specified provider, or all active widgets
+ * of the provider if target widget == null.
+ */
+ private void maskWidgetsViewsLocked(Provider provider, Widget targetWidget) {
+ final int widgetCount = provider.widgets.size();
+ if (widgetCount == 0) {
+ return;
+ }
+ final String providerPackage = provider.info.provider.getPackageName();
+ final int providerUserId = provider.getUserId();
+ Bitmap iconBitmap = createMaskedWidgetBitmap(providerPackage, providerUserId);
if (iconBitmap == null) {
return;
}
+ final boolean showBadge;
+ final Intent onClickIntent;
+ if (provider.maskedBySuspendedPackage) {
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ UserInfo userInfo = mUserManager.getUserInfo(providerUserId);
+ showBadge = userInfo.isManagedProfile();
+ onClickIntent = UnlaunchableAppActivity.createPackageSuspendedDialogIntent(
+ providerPackage, providerUserId);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ } else if (provider.maskedByQuietProfile) {
+ showBadge = true;
+ onClickIntent = UnlaunchableAppActivity.createInQuietModeDialogIntent(
+ providerUserId);
+ } else /* provider.maskedByLockedProfile */ {
+ showBadge = true;
+ onClickIntent = mKeyguardManager.createConfirmDeviceCredentialIntent(null, null,
+ providerUserId);
+ if (onClickIntent != null) {
+ onClickIntent.setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
+ }
+ }
- final int widgetCount = provider.widgets.size();
for (int j = 0; j < widgetCount; j++) {
Widget widget = provider.widgets.get(j);
- if (widget.replaceWithMaskedViewsLocked(mContext, iconBitmap)) {
- scheduleNotifyUpdateAppWidgetLocked(widget,
- widget.getEffectiveViewsLocked());
+ if (targetWidget != null && targetWidget != widget) continue;
+ PendingIntent intent = null;
+ if (onClickIntent != null) {
+ intent = PendingIntent.getActivity(mContext, widget.appWidgetId,
+ onClickIntent, PendingIntent.FLAG_UPDATE_CURRENT);
+ }
+ RemoteViews views = createMaskedWidgetRemoteViews(iconBitmap, showBadge, intent);
+ if (widget.replaceWithMaskedViewsLocked(views)) {
+ scheduleNotifyUpdateAppWidgetLocked(widget, widget.getEffectiveViewsLocked());
}
}
}
@@ -587,8 +626,7 @@
for (int j = 0; j < widgetCount; j++) {
Widget widget = provider.widgets.get(j);
if (widget.clearMaskedViewsLocked()) {
- scheduleNotifyUpdateAppWidgetLocked(widget,
- widget.getEffectiveViewsLocked());
+ scheduleNotifyUpdateAppWidgetLocked(widget, widget.getEffectiveViewsLocked());
}
}
}
@@ -2472,7 +2510,7 @@
}
synchronized (mLock) {
ensureGroupStateLoadedLocked(userId);
- reloadWidgetsMaskedStateForUser(userId);
+ reloadWidgetsMaskedStateForGroup(mSecurityPolicy.getGroupParent(userId));
final int N = mProviders.size();
for (int i = 0; i < N; i++) {
@@ -2614,10 +2652,7 @@
// If we are adding a widget it might be for a provider that
// is currently masked, if so mask the widget.
if (widget.provider.isMaskedLocked()) {
- Bitmap bitmap = createMaskedWidgetBitmap(widget.provider);
- if (bitmap != null) {
- widget.replaceWithMaskedViewsLocked(mContext, bitmap);
- }
+ maskWidgetsViewsLocked(widget.provider, widget);
} else {
widget.clearMaskedViewsLocked();
}
@@ -3014,7 +3049,6 @@
private void onUserStopped(int userId) {
synchronized (mLock) {
- boolean providersChanged = false;
boolean crossProfileWidgetsChanged = false;
// Remove widgets that have both host and provider in the user.
@@ -3050,16 +3084,8 @@
}
}
- // Remove the providers and notify hosts in other profiles.
- final int providerCount = mProviders.size();
- for (int i = providerCount - 1; i >= 0; i--) {
- Provider provider = mProviders.get(i);
- if (provider.getUserId() == userId) {
- crossProfileWidgetsChanged |= !provider.widgets.isEmpty();
- providersChanged = true;
- deleteProviderLocked(provider);
- }
- }
+ // Leave the providers present as hosts will show the widgets
+ // masked while the user is stopped.
// Remove grants for this user.
final int grantCount = mPackagesWithBindWidgetPermission.size();
@@ -3082,11 +3108,6 @@
mNextAppWidgetIds.removeAt(nextIdIndex);
}
- // Announce removed provider changes to all hosts in the group.
- if (providersChanged) {
- scheduleNotifyGroupHostsForProvidersChangedLocked(userId);
- }
-
// Save state if removing a profile changed the group state.
// Nothing will be saved if the group parent was removed.
if (crossProfileWidgetsChanged) {
@@ -3624,7 +3645,8 @@
PendingIntent broadcast;
boolean zombie; // if we're in safe mode, don't prune this just because nobody references it
- boolean maskedByProfileUnavailable;
+ boolean maskedByLockedProfile;
+ boolean maskedByQuietProfile;
boolean maskedBySuspendedPackage;
int tag = TAG_UNDEFINED; // for use while saving state (the index)
@@ -3656,22 +3678,29 @@
return "Provider{" + id + (zombie ? " Z" : "") + '}';
}
- // returns true if the provider's masked state is changed as a result
- public boolean setMaskedByProfileUnavailabledLocked(boolean masked) {
- boolean oldMaskedState = isMaskedLocked();
- maskedByProfileUnavailable = masked;
- return isMaskedLocked() != oldMaskedState;
+ // returns true if it's different from previous state.
+ public boolean setMaskedByQuietProfileLocked(boolean masked) {
+ boolean oldState = maskedByQuietProfile;
+ maskedByQuietProfile = masked;
+ return masked != oldState;
}
- // returns true if the provider's masked state is changed as a result
+ // returns true if it's different from previous state.
+ public boolean setMaskedByLockedProfileLocked(boolean masked) {
+ boolean oldState = maskedByLockedProfile;
+ maskedByLockedProfile = masked;
+ return masked != oldState;
+ }
+
+ // returns true if it's different from previous state.
public boolean setMaskedBySuspendedPackageLocked(boolean masked) {
- boolean oldMaskedState = isMaskedLocked();
+ boolean oldState = maskedBySuspendedPackage;
maskedBySuspendedPackage = masked;
- return isMaskedLocked() != oldMaskedState;
+ return masked != oldState;
}
public boolean isMaskedLocked() {
- return maskedByProfileUnavailable || maskedBySuspendedPackage;
+ return maskedByQuietProfile || maskedByLockedProfile || maskedBySuspendedPackage;
}
}
@@ -3828,14 +3857,8 @@
return "AppWidgetId{" + appWidgetId + ':' + host + ':' + provider + '}';
}
- private boolean replaceWithMaskedViewsLocked(Context context, Bitmap icon) {
- if (maskedViews != null) {
- return false;
- }
- maskedViews = new RemoteViews(context.getPackageName(), R.layout.work_widget_mask_view);
- if (icon != null) {
- maskedViews.setImageViewBitmap(R.id.work_widget_app_icon, icon);
- }
+ private boolean replaceWithMaskedViewsLocked(RemoteViews views) {
+ maskedViews = views;
return true;
}
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 25b6fdd..079b2f2 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -125,6 +125,7 @@
import com.android.server.connectivity.NetworkMonitor;
import com.android.server.connectivity.PacManager;
import com.android.server.connectivity.PermissionMonitor;
+import com.android.server.connectivity.ApfFilter;
import com.android.server.connectivity.Tethering;
import com.android.server.connectivity.Vpn;
import com.android.server.net.BaseNetworkObserver;
@@ -353,6 +354,13 @@
*/
private static final int EVENT_REGISTER_NETWORK_LISTENER_WITH_INTENT = 31;
+ /**
+ * used to push APF program to NetworkAgent
+ * replyTo = NetworkAgent message handler
+ * obj = byte[] of APF program
+ */
+ private static final int EVENT_PUSH_APF_PROGRAM_TO_NETWORK = 32;
+
/** Handler thread used for both of the handlers below. */
@VisibleForTesting
protected final HandlerThread mHandlerThread;
@@ -2190,6 +2198,7 @@
mKeepaliveTracker.handleStopAllKeepalives(nai,
ConnectivityManager.PacketKeepalive.ERROR_INVALID_NETWORK);
nai.networkMonitor.sendMessage(NetworkMonitor.CMD_NETWORK_DISCONNECTED);
+ if (nai.apfFilter != null) nai.apfFilter.shutdown();
mNetworkAgentInfos.remove(msg.replyTo);
updateClat(null, nai.linkProperties, nai);
synchronized (mNetworkForNetId) {
@@ -2404,6 +2413,13 @@
accept ? 1 : 0, always ? 1: 0, network));
}
+ public void pushApfProgramToNetwork(NetworkAgentInfo nai, byte[] program) {
+ enforceConnectivityInternalPermission();
+ Message msg = mHandler.obtainMessage(EVENT_PUSH_APF_PROGRAM_TO_NETWORK, program);
+ msg.replyTo = nai.messenger;
+ mHandler.sendMessage(msg);
+ }
+
private void handleSetAcceptUnvalidated(Network network, boolean accept, boolean always) {
if (DBG) log("handleSetAcceptUnvalidated network=" + network +
" accept=" + accept + " always=" + always);
@@ -2553,6 +2569,16 @@
handleMobileDataAlwaysOn();
break;
}
+ case EVENT_PUSH_APF_PROGRAM_TO_NETWORK: {
+ NetworkAgentInfo nai = mNetworkAgentInfos.get(msg.replyTo);
+ if (nai == null) {
+ loge("EVENT_PUSH_APF_PROGRAM_TO_NETWORK from unknown NetworkAgent");
+ } else {
+ nai.asyncChannel.sendMessage(NetworkAgent.CMD_PUSH_APF_PROGRAM,
+ (byte[]) msg.obj);
+ }
+ break;
+ }
// Sent by KeepaliveTracker to process an app request on the state machine thread.
case NetworkAgent.CMD_START_PACKET_KEEPALIVE: {
mKeepaliveTracker.handleStartKeepalive(msg);
@@ -4068,6 +4094,9 @@
if (networkAgent.clatd != null) {
networkAgent.clatd.fixupLinkProperties(oldLp);
}
+ if (networkAgent.apfFilter != null) {
+ networkAgent.apfFilter.updateFilter();
+ }
updateInterfaces(newLp, oldLp, netId);
updateMtu(newLp, oldLp);
diff --git a/services/core/java/com/android/server/LockGuard.java b/services/core/java/com/android/server/LockGuard.java
new file mode 100644
index 0000000..3a381ae
--- /dev/null
+++ b/services/core/java/com/android/server/LockGuard.java
@@ -0,0 +1,149 @@
+/*
+ * 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.
+ */
+
+package com.android.server;
+
+import android.util.ArrayMap;
+import android.util.ArraySet;
+import android.util.Slog;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+
+/**
+ * LockGuard is a mechanism to help detect lock inversions inside the system
+ * server. It works by requiring each lock acquisition site to follow this
+ * pattern:
+ *
+ * <pre>
+ * synchronized (LockGuard.guard(lock)) {
+ * }
+ * </pre>
+ *
+ * <pre>
+ * $ find services/ -name "*.java" -exec sed -i -r \
+ * 's/synchronized.?\((.+?)\)/synchronized \(com.android.server.LockGuard.guard\(\1\)\)/' {} \;
+ * </pre>
+ *
+ * The {@link #guard(Object)} method internally verifies that all locking is
+ * done in a consistent order, and will log if any inversion is detected. For
+ * example, if the calling thread is trying to acquire the
+ * {@code ActivityManager} lock while holding the {@code PackageManager} lock,
+ * it will yell.
+ * <p>
+ * This class requires no prior knowledge of locks or their ordering; it derives
+ * all of this data at runtime. However, this means the overhead is
+ * <em>substantial</em> and it should not be enabled by default. For example,
+ * here are some benchmarked timings:
+ * <ul>
+ * <li>An unguarded synchronized block takes 40ns.
+ * <li>A guarded synchronized block takes 50ns when disabled.
+ * <li>A guarded synchronized block takes 460ns per lock checked when enabled.
+ * </ul>
+ */
+public class LockGuard {
+ private static final String TAG = "LockGuard";
+
+ private static ArrayMap<Object, LockInfo> sKnown = new ArrayMap<>(0, true);
+
+ private static class LockInfo {
+ /** Friendly label to describe this lock */
+ public String label;
+
+ /** Child locks that can be acquired while this lock is already held */
+ public ArraySet<Object> children = new ArraySet<>(0, true);
+ }
+
+ private static LockInfo findOrCreateLockInfo(Object lock) {
+ LockInfo info = sKnown.get(lock);
+ if (info == null) {
+ info = new LockInfo();
+ info.label = "0x" + Integer.toHexString(System.identityHashCode(lock)) + " ["
+ + new Throwable().getStackTrace()[2].toString() + "]";
+ sKnown.put(lock, info);
+ }
+ return info;
+ }
+
+ /**
+ * Check if the calling thread is holding any locks in an inverted order.
+ *
+ * @param lock The lock the calling thread is attempting to acquire.
+ */
+ public static Object guard(Object lock) {
+ // If we already hold this lock, ignore
+ if (lock == null || Thread.holdsLock(lock)) return lock;
+
+ // Check to see if we're already holding any child locks
+ boolean triggered = false;
+ final LockInfo info = findOrCreateLockInfo(lock);
+ for (int i = 0; i < info.children.size(); i++) {
+ final Object child = info.children.valueAt(i);
+ if (child == null) continue;
+
+ if (Thread.holdsLock(child)) {
+ Slog.w(TAG, "Calling thread " + Thread.currentThread().getName() + " is holding "
+ + lockToString(child) + " while trying to acquire "
+ + lockToString(lock), new Throwable());
+ triggered = true;
+ }
+ }
+
+ if (!triggered) {
+ // If no trouble found above, record this lock as being a valid
+ // child of all locks currently being held
+ for (int i = 0; i < sKnown.size(); i++) {
+ final Object test = sKnown.keyAt(i);
+ if (test == null || test == lock) continue;
+
+ if (Thread.holdsLock(test)) {
+ sKnown.valueAt(i).children.add(lock);
+ }
+ }
+ }
+
+ return lock;
+ }
+
+ /**
+ * Report the given lock with a well-known label.
+ */
+ public static void installLock(Object lock, String label) {
+ final LockInfo info = findOrCreateLockInfo(lock);
+ info.label = label;
+ }
+
+ private static String lockToString(Object lock) {
+ final LockInfo info = sKnown.get(lock);
+ if (info != null) {
+ return info.label;
+ } else {
+ return "0x" + Integer.toHexString(System.identityHashCode(lock));
+ }
+ }
+
+ public static void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ for (int i = 0; i < sKnown.size(); i++) {
+ final Object lock = sKnown.keyAt(i);
+ final LockInfo info = sKnown.valueAt(i);
+ pw.println("Lock " + lockToString(lock) + ":");
+ for (int j = 0; j < info.children.size(); j++) {
+ pw.println(" Child " + lockToString(info.children.valueAt(j)));
+ }
+ pw.println();
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/LockSettingsService.java b/services/core/java/com/android/server/LockSettingsService.java
index ba2a2e0..6fb0671 100644
--- a/services/core/java/com/android/server/LockSettingsService.java
+++ b/services/core/java/com/android/server/LockSettingsService.java
@@ -345,9 +345,9 @@
final int userId = users.get(user).id;
final String OWNER_INFO = Secure.LOCK_SCREEN_OWNER_INFO;
String ownerInfo = Settings.Secure.getStringForUser(cr, OWNER_INFO, userId);
- if (ownerInfo != null) {
+ if (!TextUtils.isEmpty(ownerInfo)) {
setString(OWNER_INFO, ownerInfo, userId);
- Settings.Secure.putStringForUser(cr, ownerInfo, "", userId);
+ Settings.Secure.putStringForUser(cr, OWNER_INFO, "", userId);
}
// Migrate owner info enabled. Note there was a bug where older platforms only
diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java
index 853db17..329f716 100644
--- a/services/core/java/com/android/server/NetworkManagementService.java
+++ b/services/core/java/com/android/server/NetworkManagementService.java
@@ -22,8 +22,10 @@
import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_DOZABLE;
import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_DOZABLE;
import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_NONE;
+import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_POWERSAVE;
import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_STANDBY;
import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NONE;
+import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_POWERSAVE;
import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_STANDBY;
import static android.net.NetworkPolicyManager.FIREWALL_RULE_DEFAULT;
import static android.net.NetworkPolicyManager.FIREWALL_TYPE_BLACKLIST;
@@ -43,7 +45,6 @@
import static com.android.server.NetworkManagementService.NetdResponseCode.TetheringStatsListResult;
import static com.android.server.NetworkManagementService.NetdResponseCode.TtyListResult;
import static com.android.server.NetworkManagementSocketTagger.PROP_QTAGUID_ENABLED;
-
import android.annotation.NonNull;
import android.app.ActivityManagerNative;
import android.content.Context;
@@ -226,6 +227,12 @@
*/
@GuardedBy("mQuotaLock")
private SparseIntArray mUidFirewallDozableRules = new SparseIntArray();
+ /**
+ * Set of UIDs that are to be blocked/allowed by firewall controller. This set of Ids matches
+ * to device on power-save mode.
+ */
+ @GuardedBy("mQuotaLock")
+ private SparseIntArray mUidFirewallPowerSaveRules = new SparseIntArray();
/** Set of states for the child firewall chains. True if the chain is active. */
@GuardedBy("mQuotaLock")
final SparseBooleanArray mFirewallChainStates = new SparseBooleanArray();
@@ -622,6 +629,20 @@
if (mFirewallChainStates.get(FIREWALL_CHAIN_DOZABLE)) {
setFirewallChainEnabled(FIREWALL_CHAIN_DOZABLE, true);
}
+
+ size = mUidFirewallPowerSaveRules.size();
+ if (size > 0) {
+ Slog.d(TAG, "Pushing " + size + " active firewall powersave UID rules");
+ final SparseIntArray uidFirewallRules = mUidFirewallPowerSaveRules;
+ mUidFirewallPowerSaveRules = new SparseIntArray();
+ for (int i = 0; i < uidFirewallRules.size(); i++) {
+ setFirewallUidRuleInternal(FIREWALL_CHAIN_POWERSAVE, uidFirewallRules.keyAt(i),
+ uidFirewallRules.valueAt(i));
+ }
+ }
+ if (mFirewallChainStates.get(FIREWALL_CHAIN_POWERSAVE)) {
+ setFirewallChainEnabled(FIREWALL_CHAIN_POWERSAVE, true);
+ }
}
}
@@ -2020,6 +2041,9 @@
case FIREWALL_CHAIN_DOZABLE:
chainName = FIREWALL_CHAIN_NAME_DOZABLE;
break;
+ case FIREWALL_CHAIN_POWERSAVE:
+ chainName = FIREWALL_CHAIN_NAME_POWERSAVE;
+ break;
default:
throw new IllegalArgumentException("Bad child chain: " + chain);
}
@@ -2036,6 +2060,8 @@
return FIREWALL_TYPE_BLACKLIST;
case FIREWALL_CHAIN_DOZABLE:
return FIREWALL_TYPE_WHITELIST;
+ case FIREWALL_CHAIN_POWERSAVE:
+ return FIREWALL_TYPE_WHITELIST;
default:
return isFirewallEnabled() ? FIREWALL_TYPE_WHITELIST : FIREWALL_TYPE_BLACKLIST;
}
@@ -2135,6 +2161,8 @@
return mUidFirewallStandbyRules;
case FIREWALL_CHAIN_DOZABLE:
return mUidFirewallDozableRules;
+ case FIREWALL_CHAIN_POWERSAVE:
+ return mUidFirewallPowerSaveRules;
case FIREWALL_CHAIN_NONE:
return mUidFirewallRules;
default:
@@ -2148,6 +2176,8 @@
return FIREWALL_CHAIN_NAME_STANDBY;
case FIREWALL_CHAIN_DOZABLE:
return FIREWALL_CHAIN_NAME_DOZABLE;
+ case FIREWALL_CHAIN_POWERSAVE:
+ return FIREWALL_CHAIN_NAME_POWERSAVE;
case FIREWALL_CHAIN_NONE:
return FIREWALL_CHAIN_NAME_NONE;
default:
@@ -2267,43 +2297,25 @@
}
synchronized (mUidFirewallRules) {
- pw.print("UID firewall rule: [");
- final int size = mUidFirewallRules.size();
- for (int i = 0; i < size; i++) {
- pw.print(mUidFirewallRules.keyAt(i));
- pw.print(":");
- pw.print(mUidFirewallRules.valueAt(i));
- if (i < size - 1) pw.print(",");
- }
- pw.println("]");
+ dumpUidFirewallRule(pw, "", mUidFirewallRules);
}
pw.println("UID firewall standby chain enabled: " +
mFirewallChainStates.get(FIREWALL_CHAIN_STANDBY));
synchronized (mUidFirewallStandbyRules) {
- pw.print("UID firewall standby rule: [");
- final int size = mUidFirewallStandbyRules.size();
- for (int i = 0; i < size; i++) {
- pw.print(mUidFirewallStandbyRules.keyAt(i));
- pw.print(":");
- pw.print(mUidFirewallStandbyRules.valueAt(i));
- if (i < size - 1) pw.print(",");
- }
- pw.println("]");
+ dumpUidFirewallRule(pw, FIREWALL_CHAIN_NAME_STANDBY, mUidFirewallStandbyRules);
}
pw.println("UID firewall dozable chain enabled: " +
mFirewallChainStates.get(FIREWALL_CHAIN_DOZABLE));
synchronized (mUidFirewallDozableRules) {
- pw.print("UID firewall dozable rule: [");
- final int size = mUidFirewallDozableRules.size();
- for (int i = 0; i < size; i++) {
- pw.print(mUidFirewallDozableRules.keyAt(i));
- pw.print(":");
- pw.print(mUidFirewallDozableRules.valueAt(i));
- if (i < size - 1) pw.print(",");
- }
- pw.println("]");
+ dumpUidFirewallRule(pw, FIREWALL_CHAIN_NAME_DOZABLE, mUidFirewallDozableRules);
+ }
+
+ pw.println("UID firewall powersave chain enabled: " +
+ mFirewallChainStates.get(FIREWALL_CHAIN_POWERSAVE));
+ synchronized (mUidFirewallPowerSaveRules) {
+ dumpUidFirewallRule(pw, FIREWALL_CHAIN_NAME_POWERSAVE, mUidFirewallPowerSaveRules);
}
synchronized (mIdleTimerLock) {
@@ -2320,6 +2332,20 @@
pw.print("Firewall enabled: "); pw.println(mFirewallEnabled);
}
+ private void dumpUidFirewallRule(PrintWriter pw, String name, SparseIntArray rules) {
+ pw.print("UID firewall");
+ pw.print(name);
+ pw.print(" rule: [");
+ final int size = rules.size();
+ for (int i = 0; i < size; i++) {
+ pw.print(rules.keyAt(i));
+ pw.print(":");
+ pw.print(rules.valueAt(i));
+ if (i < size - 1) pw.print(",");
+ }
+ pw.println("]");
+ }
+
@Override
public void createPhysicalNetwork(int netId, String permission) {
mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
diff --git a/services/core/java/com/android/server/NetworkTimeUpdateService.java b/services/core/java/com/android/server/NetworkTimeUpdateService.java
index 3f0664d..b64c65d 100644
--- a/services/core/java/com/android/server/NetworkTimeUpdateService.java
+++ b/services/core/java/com/android/server/NetworkTimeUpdateService.java
@@ -23,8 +23,10 @@
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.pm.PackageManager;
import android.database.ContentObserver;
import android.net.ConnectivityManager;
+import android.os.Binder;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
@@ -34,10 +36,14 @@
import android.provider.Settings;
import android.util.Log;
import android.util.NtpTrustedTime;
+import android.util.TimeUtils;
import android.util.TrustedTime;
import com.android.internal.telephony.TelephonyIntents;
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+
/**
* Monitors the network time and updates the system time if it is out of sync
* and there hasn't been any NITZ update from the carrier recently.
@@ -48,7 +54,7 @@
* available.
* </p>
*/
-public class NetworkTimeUpdateService {
+public class NetworkTimeUpdateService extends Binder {
private static final String TAG = "NetworkTimeUpdateService";
private static final boolean DBG = false;
@@ -59,6 +65,8 @@
private static final String ACTION_POLL =
"com.android.server.NetworkTimeUpdateService.action.POLL";
+
+ private static final int NETWORK_CHANGE_EVENT_DELAY_MS = 1000;
private static int POLL_REQUEST = 0;
private static final long NOT_SET = -1;
@@ -245,6 +253,7 @@
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
+ if (DBG) Log.d(TAG, "Received " + action);
if (TelephonyIntents.ACTION_NETWORK_SET_TIME.equals(action)) {
mNitzTimeSetTime = SystemClock.elapsedRealtime();
} else if (TelephonyIntents.ACTION_NETWORK_SET_TIMEZONE.equals(action)) {
@@ -260,8 +269,11 @@
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (ConnectivityManager.CONNECTIVITY_ACTION.equals(action)) {
+ if (DBG) Log.d(TAG, "Received CONNECTIVITY_ACTION ");
// Don't bother checking if we have connectivity, NtpTrustedTime does that for us.
- mHandler.obtainMessage(EVENT_NETWORK_CHANGED).sendToTarget();
+ Message message = mHandler.obtainMessage(EVENT_NETWORK_CHANGED);
+ // Send with a short delay to make sure the network is ready for use
+ mHandler.sendMessageDelayed(message, NETWORK_CHANGE_EVENT_DELAY_MS);
}
}
};
@@ -308,4 +320,28 @@
mHandler.obtainMessage(mMsg).sendToTarget();
}
}
+
+ @Override
+ protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
+ != PackageManager.PERMISSION_GRANTED) {
+ pw.println("Permission Denial: can't dump NetworkTimeUpdateService from from pid="
+ + Binder.getCallingPid()
+ + ", uid=" + Binder.getCallingUid()
+ + " without permission "
+ + android.Manifest.permission.DUMP);
+ return;
+ }
+ pw.print("PollingIntervalMs: ");
+ TimeUtils.formatDuration(mPollingIntervalMs, pw);
+ pw.print("\nPollingIntervalShorterMs: ");
+ TimeUtils.formatDuration(mPollingIntervalShorterMs, pw);
+ pw.println("\nTryAgainTimesMax: " + mTryAgainTimesMax);
+ pw.print("TimeErrorThresholdMs: ");
+ TimeUtils.formatDuration(mTimeErrorThresholdMs, pw);
+ pw.println("\nTryAgainCounter: " + mTryAgainCounter);
+ pw.print("LastNtpFetchTime: ");
+ TimeUtils.formatDuration(mLastNtpFetchTime, pw);
+ pw.println();
+ }
}
diff --git a/services/core/java/com/android/server/RecoverySystemService.java b/services/core/java/com/android/server/RecoverySystemService.java
index d237fe7..d284d07 100644
--- a/services/core/java/com/android/server/RecoverySystemService.java
+++ b/services/core/java/com/android/server/RecoverySystemService.java
@@ -17,6 +17,8 @@
package com.android.server;
import android.content.Context;
+import android.net.LocalSocket;
+import android.net.LocalSocketAddress;
import android.os.IRecoverySystem;
import android.os.IRecoverySystemProgressListener;
import android.os.RecoverySystem;
@@ -26,9 +28,11 @@
import android.system.Os;
import android.util.Slog;
-import java.io.BufferedReader;
+import libcore.io.IoUtils;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
import java.io.File;
-import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
@@ -43,10 +47,10 @@
private static final String TAG = "RecoverySystemService";
private static final boolean DEBUG = false;
- // A pipe file to monitor the uncrypt progress.
- private static final String UNCRYPT_STATUS_FILE = "/cache/recovery/uncrypt_status";
- // Temporary command file to communicate between the system server and uncrypt.
- private static final String COMMAND_FILE = "/cache/recovery/command";
+ // The socket at /dev/socket/uncrypt to communicate with uncrypt.
+ private static final String UNCRYPT_SOCKET = "uncrypt";
+
+ private static final int SOCKET_CONNECTION_MAX_RETRY = 30;
private Context mContext;
@@ -79,60 +83,63 @@
return false;
}
- // Create the status pipe file to communicate with uncrypt.
- new File(UNCRYPT_STATUS_FILE).delete();
- try {
- Os.mkfifo(UNCRYPT_STATUS_FILE, 0600);
- } catch (ErrnoException e) {
- Slog.e(TAG, "ErrnoException when creating named pipe \"" + UNCRYPT_STATUS_FILE +
- "\": " + e.getMessage());
- return false;
- }
-
// Trigger uncrypt via init.
SystemProperties.set("ctl.start", "uncrypt");
- // Read the status from the pipe.
- try (BufferedReader reader = new BufferedReader(new FileReader(UNCRYPT_STATUS_FILE))) {
+ // Connect to the uncrypt service socket.
+ LocalSocket socket = connectService();
+ if (socket == null) {
+ Slog.e(TAG, "Failed to connect to uncrypt socket");
+ return false;
+ }
+
+ // Read the status from the socket.
+ try (DataInputStream dis = new DataInputStream(socket.getInputStream());
+ DataOutputStream dos = new DataOutputStream(socket.getOutputStream())) {
int lastStatus = Integer.MIN_VALUE;
while (true) {
- String str = reader.readLine();
- try {
- int status = Integer.parseInt(str);
+ int status = dis.readInt();
+ // Avoid flooding the log with the same message.
+ if (status == lastStatus && lastStatus != Integer.MIN_VALUE) {
+ continue;
+ }
+ lastStatus = status;
- // Avoid flooding the log with the same message.
- if (status == lastStatus && lastStatus != Integer.MIN_VALUE) {
- continue;
- }
- lastStatus = status;
-
- if (status >= 0 && status <= 100) {
- // Update status
- Slog.i(TAG, "uncrypt read status: " + status);
- if (listener != null) {
- try {
- listener.onProgress(status);
- } catch (RemoteException unused) {
- Slog.w(TAG, "RemoteException when posting progress");
- }
+ if (status >= 0 && status <= 100) {
+ // Update status
+ Slog.i(TAG, "uncrypt read status: " + status);
+ if (listener != null) {
+ try {
+ listener.onProgress(status);
+ } catch (RemoteException unused) {
+ Slog.w(TAG, "RemoteException when posting progress");
}
- if (status == 100) {
- Slog.i(TAG, "uncrypt successfully finished.");
- break;
- }
- } else {
- // Error in /system/bin/uncrypt.
- Slog.e(TAG, "uncrypt failed with status: " + status);
- return false;
}
- } catch (NumberFormatException unused) {
- Slog.e(TAG, "uncrypt invalid status received: " + str);
+ if (status == 100) {
+ Slog.i(TAG, "uncrypt successfully finished.");
+ // Ack receipt of the final status code. uncrypt
+ // waits for the ack so the socket won't be
+ // destroyed before we receive the code.
+ dos.writeInt(0);
+ dos.flush();
+ break;
+ }
+ } else {
+ // Error in /system/bin/uncrypt.
+ Slog.e(TAG, "uncrypt failed with status: " + status);
+ // Ack receipt of the final status code. uncrypt waits
+ // for the ack so the socket won't be destroyed before
+ // we receive the code.
+ dos.writeInt(0);
+ dos.flush();
return false;
}
}
- } catch (IOException unused) {
- Slog.e(TAG, "IOException when reading \"" + UNCRYPT_STATUS_FILE + "\".");
+ } catch (IOException e) {
+ Slog.e(TAG, "IOException when reading status: " + e);
return false;
+ } finally {
+ IoUtils.closeQuietly(socket);
}
return true;
@@ -150,29 +157,35 @@
return setupOrClearBcb(true, command);
}
- private boolean setupOrClearBcb(boolean isSetup, String command) {
- mContext.enforceCallingOrSelfPermission(android.Manifest.permission.RECOVERY, null);
-
- if (isSetup) {
- // Set up the command file to be read by uncrypt.
- try (FileWriter commandFile = new FileWriter(COMMAND_FILE)) {
- commandFile.write(command + "\n");
- } catch (IOException e) {
- Slog.e(TAG, "IOException when writing \"" + COMMAND_FILE +
- "\": " + e.getMessage());
- return false;
+ private LocalSocket connectService() {
+ LocalSocket socket = new LocalSocket();
+ boolean done = false;
+ // The uncrypt socket will be created by init upon receiving the
+ // service request. It may not be ready by this point. So we will
+ // keep retrying until success or reaching timeout.
+ for (int retry = 0; retry < SOCKET_CONNECTION_MAX_RETRY; retry++) {
+ try {
+ socket.connect(new LocalSocketAddress(UNCRYPT_SOCKET,
+ LocalSocketAddress.Namespace.RESERVED));
+ done = true;
+ break;
+ } catch (IOException unused) {
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException e) {
+ Slog.w(TAG, "Interrupted: " + e);
+ }
}
}
-
- // Create the status pipe file to communicate with uncrypt.
- new File(UNCRYPT_STATUS_FILE).delete();
- try {
- Os.mkfifo(UNCRYPT_STATUS_FILE, 0600);
- } catch (ErrnoException e) {
- Slog.e(TAG, "ErrnoException when creating named pipe \"" +
- UNCRYPT_STATUS_FILE + "\": " + e.getMessage());
- return false;
+ if (!done) {
+ Slog.e(TAG, "Timed out connecting to uncrypt socket");
+ return null;
}
+ return socket;
+ }
+
+ private boolean setupOrClearBcb(boolean isSetup, String command) {
+ mContext.enforceCallingOrSelfPermission(android.Manifest.permission.RECOVERY, null);
if (isSetup) {
SystemProperties.set("ctl.start", "setup-bcb");
@@ -180,34 +193,45 @@
SystemProperties.set("ctl.start", "clear-bcb");
}
- // Read the status from the pipe.
- try (BufferedReader reader = new BufferedReader(new FileReader(UNCRYPT_STATUS_FILE))) {
- while (true) {
- String str = reader.readLine();
- try {
- int status = Integer.parseInt(str);
-
- if (status == 100) {
- Slog.i(TAG, "uncrypt " + (isSetup ? "setup" : "clear") +
- " bcb successfully finished.");
- break;
- } else {
- // Error in /system/bin/uncrypt.
- Slog.e(TAG, "uncrypt failed with status: " + status);
- return false;
- }
- } catch (NumberFormatException unused) {
- Slog.e(TAG, "uncrypt invalid status received: " + str);
- return false;
- }
- }
- } catch (IOException unused) {
- Slog.e(TAG, "IOException when reading \"" + UNCRYPT_STATUS_FILE + "\".");
+ // Connect to the uncrypt service socket.
+ LocalSocket socket = connectService();
+ if (socket == null) {
+ Slog.e(TAG, "Failed to connect to uncrypt socket");
return false;
}
- // Delete the command file as we don't need it anymore.
- new File(COMMAND_FILE).delete();
+ try (DataInputStream dis = new DataInputStream(socket.getInputStream());
+ DataOutputStream dos = new DataOutputStream(socket.getOutputStream())) {
+ // Send the BCB commands if it's to setup BCB.
+ if (isSetup) {
+ dos.writeInt(command.length());
+ dos.writeBytes(command);
+ dos.flush();
+ }
+
+ // Read the status from the socket.
+ int status = dis.readInt();
+
+ // Ack receipt of the status code. uncrypt waits for the ack so
+ // the socket won't be destroyed before we receive the code.
+ dos.writeInt(0);
+ dos.flush();
+
+ if (status == 100) {
+ Slog.i(TAG, "uncrypt " + (isSetup ? "setup" : "clear") +
+ " bcb successfully finished.");
+ } else {
+ // Error in /system/bin/uncrypt.
+ Slog.e(TAG, "uncrypt failed with status: " + status);
+ return false;
+ }
+ } catch (IOException e) {
+ Slog.e(TAG, "IOException when getting output stream: " + e);
+ return false;
+ } finally {
+ IoUtils.closeQuietly(socket);
+ }
+
return true;
}
}
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 8c0ec78..63a0e87 100755
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -319,7 +319,7 @@
+ " (pid=" + Binder.getCallingPid()
+ ") when starting service " + service);
}
- callerFg = callerApp.setSchedGroup != Process.THREAD_GROUP_BG_NONINTERACTIVE;
+ callerFg = callerApp.setSchedGroup != ProcessList.SCHED_GROUP_BACKGROUND;
} else {
callerFg = true;
}
@@ -831,7 +831,7 @@
"BIND_TREAT_LIKE_ACTIVITY");
}
- final boolean callerFg = callerApp.setSchedGroup != Process.THREAD_GROUP_BG_NONINTERACTIVE;
+ final boolean callerFg = callerApp.setSchedGroup != ProcessList.SCHED_GROUP_BACKGROUND;
final boolean isBindExternal = (flags & Context.BIND_EXTERNAL_SERVICE) != 0;
ServiceLookupResult res =
@@ -1138,7 +1138,7 @@
for (int i=b.apps.size()-1; i>=0; i--) {
ProcessRecord client = b.apps.valueAt(i).client;
if (client != null && client.setSchedGroup
- != Process.THREAD_GROUP_BG_NONINTERACTIVE) {
+ != ProcessList.SCHED_GROUP_BACKGROUND) {
inFg = true;
break;
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java b/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java
index 4f0d4d9..f2bf4f9 100644
--- a/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java
+++ b/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java
@@ -46,6 +46,7 @@
// Available log categories in the activity manager package.
static final boolean DEBUG_ADD_REMOVE = DEBUG_ALL_ACTIVITIES || false;
+ static final boolean DEBUG_ANR = false;
static final boolean DEBUG_APP = DEBUG_ALL_ACTIVITIES || false;
static final boolean DEBUG_BACKUP = DEBUG_ALL || false;
static final boolean DEBUG_BROADCAST = DEBUG_ALL || false;
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index c81ee2c..dee3d02 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -45,6 +45,7 @@
import com.android.server.DeviceIdleController;
import com.android.server.IntentResolver;
import com.android.server.LocalServices;
+import com.android.server.LockGuard;
import com.android.server.ServiceThread;
import com.android.server.SystemService;
import com.android.server.SystemServiceManager;
@@ -283,6 +284,7 @@
import static com.android.internal.util.XmlUtils.writeIntAttribute;
import static com.android.internal.util.XmlUtils.writeLongAttribute;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_ALL;
+import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_ANR;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_BACKUP;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_BROADCAST;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_BROADCAST_BACKGROUND;
@@ -1293,6 +1295,7 @@
boolean mAlwaysFinishActivities = false;
boolean mLenientBackgroundCheck = false;
boolean mForceResizableActivities;
+ boolean mSupportsMultiWindow;
boolean mSupportsFreeformWindowManagement;
boolean mSupportsPictureInPicture;
Rect mDefaultPinnedStackBounds;
@@ -1895,6 +1898,9 @@
final int userId = msg.arg1;
mSystemServiceManager.unlockUser(userId);
mRecentTasks.loadUserRecentsLocked(userId);
+ if (userId == UserHandle.USER_SYSTEM) {
+ startPersistentApps(PackageManager.MATCH_ENCRYPTION_UNAWARE);
+ }
installEncryptionUnawareProviders(userId);
break;
}
@@ -5086,8 +5092,13 @@
int num = firstPids.size();
for (int i = 0; i < num; i++) {
synchronized (observer) {
+ if (DEBUG_ANR) Slog.d(TAG, "Collecting stacks for pid "
+ + firstPids.get(i));
+ final long sime = SystemClock.elapsedRealtime();
Process.sendSignal(firstPids.get(i), Process.SIGNAL_QUIT);
- observer.wait(200); // Wait for write-close, give up after 200msec
+ observer.wait(1000); // Wait for write-close, give up after 1 sec
+ if (DEBUG_ANR) Slog.d(TAG, "Done with pid " + firstPids.get(i)
+ + " in " + (SystemClock.elapsedRealtime()-sime) + "ms");
}
}
} catch (InterruptedException e) {
@@ -5100,7 +5111,11 @@
int[] pids = Process.getPidsForCommands(nativeProcs);
if (pids != null) {
for (int pid : pids) {
+ if (DEBUG_ANR) Slog.d(TAG, "Collecting stacks for native pid " + pid);
+ final long sime = SystemClock.elapsedRealtime();
Debug.dumpNativeBacktraceToFile(pid, tracesPath);
+ if (DEBUG_ANR) Slog.d(TAG, "Done with native pid " + pid
+ + " in " + (SystemClock.elapsedRealtime()-sime) + "ms");
}
}
}
@@ -5127,13 +5142,20 @@
numProcs++;
try {
synchronized (observer) {
+ if (DEBUG_ANR) Slog.d(TAG, "Collecting stacks for extra pid "
+ + stats.pid);
+ final long stime = SystemClock.elapsedRealtime();
Process.sendSignal(stats.pid, Process.SIGNAL_QUIT);
- observer.wait(200); // Wait for write-close, give up after 200msec
+ observer.wait(1000); // Wait for write-close, give up after 1 sec
+ if (DEBUG_ANR) Slog.d(TAG, "Done with extra pid " + stats.pid
+ + " in " + (SystemClock.elapsedRealtime()-stime) + "ms");
}
} catch (InterruptedException e) {
Slog.wtf(TAG, e);
}
-
+ } else if (DEBUG_ANR) {
+ Slog.d(TAG, "Skipping next CPU consuming process, not a java proc: "
+ + stats.pid);
}
}
}
@@ -5355,17 +5377,6 @@
@Override
public void killAllBackgroundProcesses() {
- killAllBackgroundProcesses(-1);
- }
-
- /**
- * Kills all background processes with targetSdkVersion below the specified
- * target SDK version.
- *
- * @param targetSdkVersion the target SDK version below which to kill
- * processes, or {@code -1} to kill all processes
- */
- private void killAllBackgroundProcesses(int targetSdkVersion) {
if (checkCallingPermission(android.Manifest.permission.KILL_BACKGROUND_PROCESSES)
!= PackageManager.PERMISSION_GRANTED) {
final String msg = "Permission Denial: killAllBackgroundProcesses() from pid="
@@ -5389,10 +5400,6 @@
// We don't kill persistent processes.
continue;
}
- if (targetSdkVersion > 0
- && app.info.targetSdkVersion >= targetSdkVersion) {
- continue;
- }
if (app.removed) {
procs.add(app);
} else if (app.setAdj >= ProcessList.CACHED_APP_MIN_ADJ) {
@@ -5417,6 +5424,55 @@
}
}
+ /**
+ * Kills all background processes, except those matching any of the
+ * specified properties.
+ *
+ * @param minTargetSdk the target SDK version at or above which to preserve
+ * processes, or {@code -1} to ignore the target SDK
+ * @param maxProcState the process state at or below which to preserve
+ * processes, or {@code -1} to ignore the process state
+ */
+ private void killAllBackgroundProcessesExcept(int minTargetSdk, int maxProcState) {
+ if (checkCallingPermission(android.Manifest.permission.KILL_BACKGROUND_PROCESSES)
+ != PackageManager.PERMISSION_GRANTED) {
+ final String msg = "Permission Denial: killAllBackgroundProcessesExcept() from pid="
+ + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()
+ + " requires " + android.Manifest.permission.KILL_BACKGROUND_PROCESSES;
+ Slog.w(TAG, msg);
+ throw new SecurityException(msg);
+ }
+
+ final long callingId = Binder.clearCallingIdentity();
+ try {
+ synchronized (this) {
+ final ArrayList<ProcessRecord> procs = new ArrayList<>();
+ final int NP = mProcessNames.getMap().size();
+ for (int ip = 0; ip < NP; ip++) {
+ final SparseArray<ProcessRecord> apps = mProcessNames.getMap().valueAt(ip);
+ final int NA = apps.size();
+ for (int ia = 0; ia < NA; ia++) {
+ final ProcessRecord app = apps.valueAt(ia);
+ if (app.removed) {
+ procs.add(app);
+ } else if ((minTargetSdk < 0 || app.info.targetSdkVersion < minTargetSdk)
+ && (maxProcState < 0 || app.setProcState > maxProcState)) {
+ app.removed = true;
+ procs.add(app);
+ }
+ }
+ }
+
+ final int N = procs.size();
+ for (int i = 0; i < N; i++) {
+ removeProcessLocked(procs.get(i), false, true, "kill all background except");
+ }
+ }
+ } finally {
+ Binder.restoreCallingIdentity(callingId);
+ }
+ }
+
@Override
public void forceStopPackage(final String packageName, int userId) {
if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
@@ -6173,7 +6229,7 @@
app.makeActive(thread, mProcessStats);
app.curAdj = app.setAdj = ProcessList.INVALID_ADJ;
- app.curSchedGroup = app.setSchedGroup = Process.THREAD_GROUP_DEFAULT;
+ app.curSchedGroup = app.setSchedGroup = ProcessList.SCHED_GROUP_DEFAULT;
app.forcingToForeground = null;
updateProcessForegroundLocked(app, false, false);
app.hasShownUi = false;
@@ -9164,7 +9220,7 @@
// Kill the running processes.
for (int i = 0; i < procsToKill.size(); i++) {
ProcessRecord pr = procsToKill.get(i);
- if (pr.setSchedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE
+ if (pr.setSchedGroup == ProcessList.SCHED_GROUP_BACKGROUND
&& pr.curReceiver == null) {
pr.kill("remove task", true);
} else {
@@ -9489,7 +9545,7 @@
* docked stack. Pass {@code null} to use default bounds.
*/
@Override
- public void moveTaskToDockedStack(int taskId, int createMode, boolean toTop, boolean animate,
+ public boolean moveTaskToDockedStack(int taskId, int createMode, boolean toTop, boolean animate,
Rect initialBounds) {
enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "moveTaskToDockedStack()");
synchronized (this) {
@@ -9498,7 +9554,8 @@
if (DEBUG_STACK) Slog.d(TAG_STACK, "moveTaskToDockedStack: moving task=" + taskId
+ " to createMode=" + createMode + " toTop=" + toTop);
mWindowManager.setDockedStackCreateState(createMode, initialBounds);
- mStackSupervisor.moveTaskToStackLocked(taskId, DOCKED_STACK_ID, toTop, !FORCE_FOCUS,
+ return mStackSupervisor.moveTaskToStackLocked(
+ taskId, DOCKED_STACK_ID, toTop, !FORCE_FOCUS,
"moveTaskToDockedStack", animate);
} finally {
Binder.restoreCallingIdentity(ident);
@@ -9577,6 +9634,20 @@
}
@Override
+ public void resizePinnedStack(Rect pinnedBounds, Rect tempPinnedTaskBounds) {
+ enforceCallingPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS,
+ "resizePinnedStack()");
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ synchronized (this) {
+ mStackSupervisor.resizePinnedStackLocked(pinnedBounds, tempPinnedTaskBounds);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+
+ @Override
public void positionTaskInStack(int taskId, int stackId, int position) {
enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "positionTaskInStack()");
if (stackId == HOME_STACK_ID) {
@@ -10424,7 +10495,7 @@
cpi.packageName, r.userId)) {
final boolean callerForeground = r != null ? r.setSchedGroup
- != Process.THREAD_GROUP_BG_NONINTERACTIVE : true;
+ != ProcessList.SCHED_GROUP_BACKGROUND : true;
// Show a permission review UI only for starting from a foreground app
if (!callerForeground) {
@@ -10744,12 +10815,13 @@
return;
}
- final long token = Binder.clearCallingIdentity();
- try {
- mAppErrors.appNotResponding(host, null, null, false, "ContentProvider not responding");
- } finally {
- Binder.restoreCallingIdentity(token);
- }
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ mAppErrors.appNotResponding(host, null, null, false,
+ "ContentProvider not responding");
+ }
+ });
}
public final void installSystemProviders() {
@@ -10778,6 +10850,23 @@
//mUsageStatsService.monitorPackages();
}
+ private void startPersistentApps(int matchFlags) {
+ if (mFactoryTest == FactoryTest.FACTORY_TEST_LOW_LEVEL) return;
+
+ synchronized (this) {
+ try {
+ final List<ApplicationInfo> apps = AppGlobals.getPackageManager()
+ .getPersistentApplications(STOCK_PM_FLAGS | matchFlags);
+ for (ApplicationInfo app : apps) {
+ if (!"android".equals(app.packageName)) {
+ addAppLocked(app, false, null /* ABI override */);
+ }
+ }
+ } catch (RemoteException ex) {
+ }
+ }
+ }
+
/**
* When a user is unlocked, we need to install encryption-unaware providers
* belonging to any running apps.
@@ -10794,8 +10883,7 @@
// We're only interested in providers that are encryption unaware, and
// we don't care about uninstalled apps, since there's no way they're
// running at this point.
- final int matchFlags = GET_PROVIDERS | MATCH_ENCRYPTION_UNAWARE
- | MATCH_DEBUG_TRIAGED_MISSING;
+ final int matchFlags = GET_PROVIDERS | MATCH_ENCRYPTION_UNAWARE;
synchronized (this) {
final int NP = mProcessNames.getMap().size();
@@ -12316,6 +12404,7 @@
final boolean supportsPictureInPicture =
mContext.getPackageManager().hasSystemFeature(FEATURE_PICTURE_IN_PICTURE);
+ final boolean supportsMultiWindow = ActivityManager.supportsMultiWindow();
final String debugApp = Settings.Global.getString(resolver, DEBUG_APP);
final boolean waitForDebugger = Settings.Global.getInt(resolver, WAIT_FOR_DEBUGGER, 0) != 0;
final boolean alwaysFinishActivities =
@@ -12342,8 +12431,15 @@
mLenientBackgroundCheck = lenientBackgroundCheck;
mForceResizableActivities = forceResizable;
mWindowManager.setForceResizableTasks(mForceResizableActivities);
- mSupportsFreeformWindowManagement = freeformWindowManagement || forceResizable;
- mSupportsPictureInPicture = supportsPictureInPicture || forceResizable;
+ if (supportsMultiWindow || forceResizable) {
+ mSupportsMultiWindow = true;
+ mSupportsFreeformWindowManagement = freeformWindowManagement || forceResizable;
+ mSupportsPictureInPicture = supportsPictureInPicture || forceResizable;
+ } else {
+ mSupportsMultiWindow = false;
+ mSupportsFreeformWindowManagement = false;
+ mSupportsPictureInPicture = false;
+ }
// This happens before any activities are started, so we can
// change mConfiguration in-place.
updateConfigurationLocked(configuration, null, true);
@@ -12681,26 +12777,9 @@
mSystemServiceManager.startUser(currentUserId);
synchronized (this) {
- if (mFactoryTest != FactoryTest.FACTORY_TEST_LOW_LEVEL) {
- try {
- List apps = AppGlobals.getPackageManager().
- getPersistentApplications(STOCK_PM_FLAGS);
- if (apps != null) {
- int N = apps.size();
- int i;
- for (i=0; i<N; i++) {
- ApplicationInfo info
- = (ApplicationInfo)apps.get(i);
- if (info != null &&
- !info.packageName.equals("android")) {
- addAppLocked(info, false, null /* ABI override */);
- }
- }
- }
- } catch (RemoteException ex) {
- // pm is in same process, this will never happen.
- }
- }
+ // Only start up encryption-aware persistent apps; once user is
+ // unlocked we'll come back around and start unaware apps
+ startPersistentApps(PackageManager.MATCH_ENCRYPTION_AWARE);
// Start up initial activity.
mBooting = true;
@@ -13585,6 +13664,8 @@
synchronized (this) {
mServices.dumpServicesLocked(fd, pw, args, opti, true, dumpClient, dumpPackage);
}
+ } else if ("locks".equals(cmd)) {
+ LockGuard.dump(fd, pw, args);
} else {
// Dumping a single activity?
if (!dumpActivity(fd, pw, cmd, args, opti, dumpAll)) {
@@ -14731,13 +14812,13 @@
String oomAdj = ProcessList.makeOomAdjString(r.setAdj);
char schedGroup;
switch (r.setSchedGroup) {
- case Process.THREAD_GROUP_BG_NONINTERACTIVE:
+ case ProcessList.SCHED_GROUP_BACKGROUND:
schedGroup = 'B';
break;
- case Process.THREAD_GROUP_DEFAULT:
+ case ProcessList.SCHED_GROUP_DEFAULT:
schedGroup = 'F';
break;
- case Process.THREAD_GROUP_TOP_APP:
+ case ProcessList.SCHED_GROUP_TOP_APP:
schedGroup = 'T';
break;
default:
@@ -17145,10 +17226,11 @@
String ssp;
if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
boolean removed = Intent.ACTION_PACKAGE_REMOVED.equals(action);
- boolean fullUninstall = removed &&
- !intent.getBooleanExtra(Intent.EXTRA_REPLACING, false);
+ final boolean replacing =
+ intent.getBooleanExtra(Intent.EXTRA_REPLACING, false);
final boolean killProcess =
!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false);
+ final boolean fullUninstall = removed && !replacing;
if (killProcess) {
forceStopPackageLocked(ssp, UserHandle.getAppId(
intent.getIntExtra(Intent.EXTRA_UID, -1)),
@@ -17156,7 +17238,10 @@
removed ? "pkg removed" : "pkg changed");
}
if (removed) {
- sendPackageBroadcastLocked(IApplicationThread.PACKAGE_REMOVED,
+ final int cmd = killProcess
+ ? IApplicationThread.PACKAGE_REMOVED
+ : IApplicationThread.PACKAGE_REMOVED_DONT_KILL;
+ sendPackageBroadcastLocked(cmd,
new String[] {ssp}, userId);
if (fullUninstall) {
mAppOpsService.packageRemoved(
@@ -17191,7 +17276,23 @@
break;
}
break;
+ case Intent.ACTION_PACKAGE_REPLACED:
+ {
+ final Uri data = intent.getData();
+ final String ssp;
+ if (data != null && (ssp = data.getSchemeSpecificPart()) != null) {
+ final ApplicationInfo aInfo =
+ getPackageManagerInternalLocked().getApplicationInfo(
+ ssp,
+ userId);
+ mStackSupervisor.updateActivityApplicationInfoLocked(aInfo);
+ sendPackageBroadcastLocked(IApplicationThread.PACKAGE_REPLACED,
+ new String[] {ssp}, userId);
+ }
+ break;
+ }
case Intent.ACTION_PACKAGE_ADDED:
+ {
// Special case for adding a package: by default turn on compatibility mode.
Uri data = intent.getData();
String ssp;
@@ -17209,6 +17310,7 @@
}
}
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
@@ -18050,7 +18152,8 @@
final boolean isDensityChange = (changes & ActivityInfo.CONFIG_DENSITY) != 0;
if (isDensityChange) {
- killAllBackgroundProcesses(Build.VERSION_CODES.N);
+ killAllBackgroundProcessesExcept(Build.VERSION_CODES.N,
+ ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE);
}
for (int i=mLruProcesses.size()-1; i>=0; i--) {
@@ -18271,7 +18374,7 @@
if (app.thread == null) {
app.adjSeq = mAdjSeq;
- app.curSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
+ app.curSchedGroup = ProcessList.SCHED_GROUP_BACKGROUND;
app.curProcState = ActivityManager.PROCESS_STATE_CACHED_EMPTY;
return (app.curAdj=app.curRawAdj=ProcessList.CACHED_APP_MAX_ADJ);
}
@@ -18291,7 +18394,7 @@
app.adjSeq = mAdjSeq;
app.curRawAdj = app.maxAdj;
app.foregroundActivities = false;
- app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
+ app.curSchedGroup = ProcessList.SCHED_GROUP_DEFAULT;
app.curProcState = ActivityManager.PROCESS_STATE_PERSISTENT;
// System processes can do UI, and when they do we want to have
// them trim their memory after the user leaves the UI. To
@@ -18328,14 +18431,14 @@
if (app == TOP_APP) {
// The last app on the list is the foreground app.
adj = ProcessList.FOREGROUND_APP_ADJ;
- schedGroup = Process.THREAD_GROUP_TOP_APP;
+ schedGroup = ProcessList.SCHED_GROUP_TOP_APP;
app.adjType = "top-activity";
foregroundActivities = true;
procState = PROCESS_STATE_CUR_TOP;
} else if (app.instrumentationClass != null) {
// Don't want to kill running instrumentation.
adj = ProcessList.FOREGROUND_APP_ADJ;
- schedGroup = Process.THREAD_GROUP_DEFAULT;
+ schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
app.adjType = "instrumentation";
procState = ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE;
} else if ((queue = isReceivingBroadcast(app)) != null) {
@@ -18345,7 +18448,7 @@
// broadcast as reflected by which queue it's active in.
adj = ProcessList.FOREGROUND_APP_ADJ;
schedGroup = (queue == mFgBroadcastQueue)
- ? Process.THREAD_GROUP_DEFAULT : Process.THREAD_GROUP_BG_NONINTERACTIVE;
+ ? ProcessList.SCHED_GROUP_DEFAULT : ProcessList.SCHED_GROUP_BACKGROUND;
app.adjType = "broadcast";
procState = ActivityManager.PROCESS_STATE_RECEIVER;
} else if (app.executingServices.size() > 0) {
@@ -18353,13 +18456,13 @@
// counts as being in the foreground.
adj = ProcessList.FOREGROUND_APP_ADJ;
schedGroup = app.execServicesFg ?
- Process.THREAD_GROUP_DEFAULT : Process.THREAD_GROUP_BG_NONINTERACTIVE;
+ ProcessList.SCHED_GROUP_DEFAULT : ProcessList.SCHED_GROUP_BACKGROUND;
app.adjType = "exec-service";
procState = ActivityManager.PROCESS_STATE_SERVICE;
//Slog.i(TAG, "EXEC " + (app.execServicesFg ? "FG" : "BG") + ": " + app);
} else {
// As far as we know the process is empty. We may change our mind later.
- schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
+ schedGroup = ProcessList.SCHED_GROUP_BACKGROUND;
// At this point we don't actually know the adjustment. Use the cached adj
// value that the caller wants us to.
adj = cachedAdj;
@@ -18388,7 +18491,7 @@
if (procState > PROCESS_STATE_CUR_TOP) {
procState = PROCESS_STATE_CUR_TOP;
}
- schedGroup = Process.THREAD_GROUP_DEFAULT;
+ schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
app.cached = false;
app.empty = false;
foregroundActivities = true;
@@ -18407,7 +18510,7 @@
if (procState > PROCESS_STATE_CUR_TOP) {
procState = PROCESS_STATE_CUR_TOP;
}
- schedGroup = Process.THREAD_GROUP_DEFAULT;
+ schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
app.cached = false;
app.empty = false;
foregroundActivities = true;
@@ -18451,7 +18554,7 @@
procState = ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE;
app.cached = false;
app.adjType = "fg-service";
- schedGroup = Process.THREAD_GROUP_DEFAULT;
+ schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
} else if (app.forcingToForeground != null) {
// The user is aware of this app, so make it visible.
adj = ProcessList.PERCEPTIBLE_APP_ADJ;
@@ -18459,7 +18562,7 @@
app.cached = false;
app.adjType = "force-fg";
app.adjSource = app.forcingToForeground;
- schedGroup = Process.THREAD_GROUP_DEFAULT;
+ schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
}
}
@@ -18467,7 +18570,7 @@
if (adj > ProcessList.HEAVY_WEIGHT_APP_ADJ) {
// We don't want to kill the current heavy-weight process.
adj = ProcessList.HEAVY_WEIGHT_APP_ADJ;
- schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
+ schedGroup = ProcessList.SCHED_GROUP_BACKGROUND;
app.cached = false;
app.adjType = "heavy";
}
@@ -18481,7 +18584,7 @@
// This process is hosting what we currently consider to be the
// home app, so we don't want to let it go into the background.
adj = ProcessList.HOME_APP_ADJ;
- schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
+ schedGroup = ProcessList.SCHED_GROUP_BACKGROUND;
app.cached = false;
app.adjType = "home";
}
@@ -18496,7 +18599,7 @@
// We want to try to keep it around more aggressively, to give
// a good experience around switching between two apps.
adj = ProcessList.PREVIOUS_APP_ADJ;
- schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
+ schedGroup = ProcessList.SCHED_GROUP_BACKGROUND;
app.cached = false;
app.adjType = "previous";
}
@@ -18536,7 +18639,7 @@
for (int is = app.services.size()-1;
is >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ
- || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE
+ || schedGroup == ProcessList.SCHED_GROUP_BACKGROUND
|| procState > ActivityManager.PROCESS_STATE_TOP);
is--) {
ServiceRecord s = app.services.valueAt(is);
@@ -18574,13 +18677,13 @@
}
for (int conni = s.connections.size()-1;
conni >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ
- || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE
+ || schedGroup == ProcessList.SCHED_GROUP_BACKGROUND
|| procState > ActivityManager.PROCESS_STATE_TOP);
conni--) {
ArrayList<ConnectionRecord> clist = s.connections.valueAt(conni);
for (int i = 0;
i < clist.size() && (adj > ProcessList.FOREGROUND_APP_ADJ
- || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE
+ || schedGroup == ProcessList.SCHED_GROUP_BACKGROUND
|| procState > ActivityManager.PROCESS_STATE_TOP);
i++) {
// XXX should compute this based on the max of
@@ -18672,7 +18775,7 @@
if ((cr.flags&Context.BIND_IMPORTANT) != 0) {
schedGroup = client.curSchedGroup;
} else {
- schedGroup = Process.THREAD_GROUP_DEFAULT;
+ schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
}
}
if (clientProcState <= ActivityManager.PROCESS_STATE_TOP) {
@@ -18742,9 +18845,9 @@
adj = ProcessList.FOREGROUND_APP_ADJ;
if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
if ((cr.flags&Context.BIND_IMPORTANT) != 0) {
- schedGroup = Process.THREAD_GROUP_TOP_APP;
+ schedGroup = ProcessList.SCHED_GROUP_TOP_APP;
} else {
- schedGroup = Process.THREAD_GROUP_DEFAULT;
+ schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
}
}
app.cached = false;
@@ -18762,13 +18865,13 @@
for (int provi = app.pubProviders.size()-1;
provi >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ
- || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE
+ || schedGroup == ProcessList.SCHED_GROUP_BACKGROUND
|| procState > ActivityManager.PROCESS_STATE_TOP);
provi--) {
ContentProviderRecord cpr = app.pubProviders.valueAt(provi);
for (int i = cpr.connections.size()-1;
i >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ
- || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE
+ || schedGroup == ProcessList.SCHED_GROUP_BACKGROUND
|| procState > ActivityManager.PROCESS_STATE_TOP);
i--) {
ContentProviderConnection conn = cpr.connections.get(i);
@@ -18826,7 +18929,7 @@
procState = clientProcState;
}
if (client.curSchedGroup > schedGroup) {
- schedGroup = Process.THREAD_GROUP_DEFAULT;
+ schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
}
}
// If the provider has external (non-framework) process
@@ -18835,7 +18938,7 @@
if (cpr.hasExternalProcessHandles()) {
if (adj > ProcessList.FOREGROUND_APP_ADJ) {
adj = ProcessList.FOREGROUND_APP_ADJ;
- schedGroup = Process.THREAD_GROUP_DEFAULT;
+ schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
app.cached = false;
app.adjType = "provider";
app.adjTarget = cpr.name;
@@ -18849,7 +18952,7 @@
if (app.lastProviderTime > 0 && (app.lastProviderTime+CONTENT_PROVIDER_RETAIN_TIME) > now) {
if (adj > ProcessList.PREVIOUS_APP_ADJ) {
adj = ProcessList.PREVIOUS_APP_ADJ;
- schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
+ schedGroup = ProcessList.SCHED_GROUP_BACKGROUND;
app.cached = false;
app.adjType = "provider";
}
@@ -18928,7 +19031,7 @@
if (adj > app.maxAdj) {
adj = app.maxAdj;
if (app.maxAdj <= ProcessList.PERCEPTIBLE_APP_ADJ) {
- schedGroup = Process.THREAD_GROUP_DEFAULT;
+ schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
}
}
@@ -19344,17 +19447,29 @@
if (app.setSchedGroup != app.curSchedGroup) {
app.setSchedGroup = app.curSchedGroup;
if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG_OOM_ADJ,
- "Setting process group of " + app.processName
+ "Setting sched group of " + app.processName
+ " to " + app.curSchedGroup);
if (app.waitingToKill != null && app.curReceiver == null
- && app.setSchedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE) {
+ && app.setSchedGroup == ProcessList.SCHED_GROUP_BACKGROUND) {
app.kill(app.waitingToKill, true);
success = false;
} else {
+ int processGroup;
+ switch (app.curSchedGroup) {
+ case ProcessList.SCHED_GROUP_BACKGROUND:
+ processGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
+ break;
+ case ProcessList.SCHED_GROUP_TOP_APP:
+ processGroup = Process.THREAD_GROUP_TOP_APP;
+ break;
+ default:
+ processGroup = Process.THREAD_GROUP_DEFAULT;
+ break;
+ }
if (true) {
long oldId = Binder.clearCallingIdentity();
try {
- Process.setProcessGroup(app.pid, app.curSchedGroup);
+ Process.setProcessGroup(app.pid, processGroup);
} catch (Exception e) {
Slog.w(TAG, "Failed setting process group of " + app.pid
+ " to " + app.curSchedGroup);
@@ -19365,7 +19480,7 @@
} else {
if (app.thread != null) {
try {
- app.thread.setSchedulingGroup(app.curSchedGroup);
+ app.thread.setSchedulingGroup(processGroup);
} catch (RemoteException e) {
}
}
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index d5e40cf..e430dad 100755
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -76,6 +76,7 @@
import java.io.PrintWriter;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.HashSet;
import java.util.Objects;
@@ -252,6 +253,10 @@
pw.print(prefix); pw.print("resDir="); pw.println(appInfo.publicSourceDir);
}
pw.print(prefix); pw.print("dataDir="); pw.println(appInfo.dataDir);
+ if (appInfo.splitSourceDirs != null) {
+ pw.print(prefix); pw.print("splitDir=");
+ pw.println(Arrays.toString(appInfo.splitSourceDirs));
+ }
}
pw.print(prefix); pw.print("stateNotNeeded="); pw.print(stateNotNeeded);
pw.print(" componentSpecified="); pw.print(componentSpecified);
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 769bee4..74c8363 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -65,6 +65,8 @@
import android.content.ComponentName;
import android.content.Intent;
import android.content.pm.ActivityInfo;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.net.Uri;
@@ -184,7 +186,7 @@
* The back history of all previous (and possibly still
* running) activities. It contains #TaskRecord objects.
*/
- private ArrayList<TaskRecord> mTaskHistory = new ArrayList<>();
+ private final ArrayList<TaskRecord> mTaskHistory = new ArrayList<>();
/**
* Used for validating app tokens with window manager.
@@ -839,6 +841,18 @@
}
}
+ void updateActivityApplicationInfoLocked(ApplicationInfo aInfo) {
+ final String packageName = aInfo.packageName;
+ for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
+ final List<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
+ for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
+ if (packageName.equals(activities.get(activityNdx).packageName)) {
+ activities.get(activityNdx).info.applicationInfo = aInfo;
+ }
+ }
+ }
+ }
+
/**
* @return true if something must be done before going to sleep.
*/
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index c7fc5e2..48f31f9 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -1700,6 +1700,15 @@
return false;
}
+ void updateActivityApplicationInfoLocked(ApplicationInfo aInfo) {
+ for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
+ final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
+ for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
+ stacks.get(stackNdx).updateActivityApplicationInfoLocked(aInfo);
+ }
+ }
+ }
+
TaskRecord finishTopRunningActivityLocked(ProcessRecord app, String reason) {
TaskRecord finishedTask = null;
ActivityStack focusedStack = getFocusedStack();
@@ -2034,6 +2043,25 @@
|| tempOtherTaskInsetBounds != null);
}
+ void resizePinnedStackLocked(Rect pinnedBounds, Rect tempPinnedTaskBounds) {
+ final ActivityStack stack = getStack(PINNED_STACK_ID);
+ if (stack == null) {
+ Slog.w(TAG, "resizePinnedStackLocked: pinned stack not found");
+ return;
+ }
+ Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "am.resizePinnedStack");
+ mWindowManager.deferSurfaceLayout();
+ try {
+ ActivityRecord r = stack.topRunningActivityLocked();
+ resizeStackUncheckedLocked(stack, pinnedBounds, tempPinnedTaskBounds,
+ null);
+ ensureConfigurationAndResume(stack, r, false);
+ } finally {
+ mWindowManager.continueSurfaceLayout();
+ Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
+ }
+ }
+
boolean resizeTaskLocked(TaskRecord task, Rect bounds, int resizeMode, boolean preserveWindow) {
if (!task.isResizeable()) {
Slog.w(TAG, "resizeTask: task " + task + " not resizeable.");
@@ -2174,6 +2202,12 @@
*/
ActivityStack moveTaskToStackUncheckedLocked(
TaskRecord task, int stackId, boolean toTop, boolean forceFocus, String reason) {
+
+ if (StackId.isMultiWindowStack(stackId) && !mService.mSupportsMultiWindow) {
+ throw new IllegalStateException("moveTaskToStackUncheckedLocked: Device doesn't "
+ + "support multi-window task=" + task + " to stackId=" + stackId);
+ }
+
final ActivityRecord r = task.getTopActivity();
final ActivityStack prevStack = task.stack;
final boolean wasFocused = isFocusedStack(prevStack) && (topRunningActivityLocked() == r);
@@ -2184,8 +2218,6 @@
final boolean wasFront = isFrontStack(prevStack)
&& (prevStack.topRunningActivityLocked() == r);
- final int resizeMode = task.mResizeMode;
-
if (stackId == DOCKED_STACK_ID && !task.isResizeable()) {
// We don't allow moving a unresizeable task to the docked stack since the docked
// stack is used for split-screen mode and will cause things like the docked divider to
@@ -2213,18 +2245,18 @@
return stack;
}
- void moveTaskToStackLocked(int taskId, int stackId, boolean toTop, boolean forceFocus,
+ boolean moveTaskToStackLocked(int taskId, int stackId, boolean toTop, boolean forceFocus,
String reason, boolean animate) {
final TaskRecord task = anyTaskForIdLocked(taskId);
if (task == null) {
Slog.w(TAG, "moveTaskToStack: no task for id=" + taskId);
- return;
+ return false;
}
if (task.stack != null && task.stack.mStackId == stackId) {
// You are already in the right stack silly...
Slog.i(TAG, "moveTaskToStack: taskId=" + taskId + " already in stackId=" + stackId);
- return;
+ return true;
}
if (stackId == FREEFORM_WORKSPACE_STACK_ID && !mService.mSupportsFreeformWindowManagement) {
@@ -2293,6 +2325,8 @@
resumeFocusedStackTopActivityLocked();
showNonResizeableDockToastIfNeeded(task, preferredLaunchStackId, stackId);
+
+ return (preferredLaunchStackId == stackId);
}
boolean moveTopStackActivityToPinnedStackLocked(int stackId, Rect bounds) {
diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java
index bcdc800..46389e2 100644
--- a/services/core/java/com/android/server/am/ActivityStarter.java
+++ b/services/core/java/com/android/server/am/ActivityStarter.java
@@ -1772,12 +1772,13 @@
return false;
}
- if (stackId == DOCKED_STACK_ID && r.canGoInDockedStack()) {
- return true;
+ if (stackId != FULLSCREEN_WORKSPACE_STACK_ID
+ && (!mService.mSupportsMultiWindow || !r.isResizeableOrForced())) {
+ return false;
}
- if (stackId != FULLSCREEN_WORKSPACE_STACK_ID && !r.isResizeableOrForced()) {
- return false;
+ if (stackId == DOCKED_STACK_ID && r.canGoInDockedStack()) {
+ return true;
}
if (stackId == FREEFORM_WORKSPACE_STACK_ID && !mService.mSupportsFreeformWindowManagement) {
diff --git a/services/core/java/com/android/server/am/AppErrors.java b/services/core/java/com/android/server/am/AppErrors.java
index 055935d..6cd7561 100644
--- a/services/core/java/com/android/server/am/AppErrors.java
+++ b/services/core/java/com/android/server/am/AppErrors.java
@@ -61,6 +61,7 @@
import java.util.concurrent.Semaphore;
import static com.android.server.Watchdog.NATIVE_STACKS_OF_INTEREST;
+import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_ANR;
import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.am.ActivityManagerService.MY_PID;
@@ -806,8 +807,10 @@
if (pid > 0 && pid != app.pid && pid != parentPid && pid != MY_PID) {
if (r.persistent) {
firstPids.add(pid);
+ if (DEBUG_ANR) Slog.i(TAG, "Adding persistent proc: " + r);
} else {
lastPids.put(pid, Boolean.TRUE);
+ if (DEBUG_ANR) Slog.i(TAG, "Adding ANR proc: " + r);
}
}
}
diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java
index 37b0af1..45e3a76 100644
--- a/services/core/java/com/android/server/am/BroadcastQueue.java
+++ b/services/core/java/com/android/server/am/BroadcastQueue.java
@@ -654,7 +654,7 @@
}
final boolean callerForeground = receiverRecord.callerApp != null
- ? receiverRecord.callerApp.setSchedGroup != Process.THREAD_GROUP_BG_NONINTERACTIVE
+ ? receiverRecord.callerApp.setSchedGroup != ProcessList.SCHED_GROUP_BACKGROUND
: true;
// Show a permission review UI only for explicit broadcast from a foreground app
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index b49370b..f073e5c 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -124,6 +124,13 @@
// Memory pages are 4K.
static final int PAGE_SIZE = 4*1024;
+ // Activity manager's version of Process.THREAD_GROUP_BG_NONINTERACTIVE
+ static final int SCHED_GROUP_BACKGROUND = 0;
+ // Activity manager's version of Process.THREAD_GROUP_DEFAULT
+ static final int SCHED_GROUP_DEFAULT = 1;
+ // Activity manager's version of Process.THREAD_GROUP_TOP_APP
+ static final int SCHED_GROUP_TOP_APP = 2;
+
// The minimum number of cached apps we want to be able to keep around,
// without empty apps being able to push them out of memory.
static final int MIN_CACHED_APPS = 2;
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 5a3639a..f2a9c2c 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -849,7 +849,7 @@
AudioSystem.setForceUse(AudioSystem.FOR_DOCK,
mDockAudioMediaEnabled ?
AudioSystem.FORCE_ANALOG_DOCK : AudioSystem.FORCE_NONE);
- readEncodedSurroundMode(mContentResolver);
+ sendEncodedSurroundMode(mContentResolver);
}
if (mHdmiManager != null) {
synchronized (mHdmiManager) {
@@ -1023,7 +1023,7 @@
AudioSystem.setMasterMono(masterMono);
}
- private void readEncodedSurroundMode(ContentResolver cr)
+ private void sendEncodedSurroundMode(ContentResolver cr)
{
int encodedSurroundMode = Settings.Global.getInt(
cr, Settings.Global.ENCODED_SURROUND_OUTPUT,
@@ -1102,7 +1102,7 @@
updateRingerModeAffectedStreams();
readDockAudioSettings(cr);
- readEncodedSurroundMode(cr);
+ sendEncodedSurroundMode(cr);
}
mMuteAffectedStreams = System.getIntForUser(cr,
@@ -4642,6 +4642,8 @@
private class SettingsObserver extends ContentObserver {
+ private int mEncodedSurroundMode;
+
SettingsObserver() {
super(new Handler());
mContentResolver.registerContentObserver(Settings.System.getUriFor(
@@ -4650,6 +4652,12 @@
Settings.Global.DOCK_AUDIO_MEDIA_ENABLED), false, this);
mContentResolver.registerContentObserver(Settings.System.getUriFor(
Settings.System.MASTER_MONO), false, this);
+
+ mEncodedSurroundMode = Settings.Global.getInt(
+ mContentResolver, Settings.Global.ENCODED_SURROUND_OUTPUT,
+ Settings.Global.ENCODED_SURROUND_OUTPUT_AUTO);
+ mContentResolver.registerContentObserver(Settings.Global.getUriFor(
+ Settings.Global.ENCODED_SURROUND_OUTPUT), false, this);
}
@Override
@@ -4669,7 +4677,33 @@
}
readDockAudioSettings(mContentResolver);
updateMasterMono(mContentResolver);
- readEncodedSurroundMode(mContentResolver);
+ updateEncodedSurroundOutput();
+ }
+ }
+
+ private void updateEncodedSurroundOutput() {
+ int newSurroundMode = Settings.Global.getInt(
+ mContentResolver, Settings.Global.ENCODED_SURROUND_OUTPUT,
+ Settings.Global.ENCODED_SURROUND_OUTPUT_AUTO);
+ // Did it change?
+ if (mEncodedSurroundMode != newSurroundMode) {
+ // Send to AudioPolicyManager
+ sendEncodedSurroundMode(newSurroundMode);
+ synchronized(mConnectedDevices) {
+ // Is HDMI connected?
+ String key = makeDeviceListKey(AudioSystem.DEVICE_OUT_HDMI, "");
+ DeviceListSpec deviceSpec = mConnectedDevices.get(key);
+ if (deviceSpec != null) {
+ // Toggle HDMI to retrigger broadcast with proper formats.
+ setWiredDeviceConnectionState(AudioSystem.DEVICE_OUT_HDMI,
+ AudioSystem.DEVICE_STATE_UNAVAILABLE, "", "",
+ "android"); // disconnect
+ setWiredDeviceConnectionState(AudioSystem.DEVICE_OUT_HDMI,
+ AudioSystem.DEVICE_STATE_AVAILABLE, "", "",
+ "android"); // reconnect
+ }
+ }
+ mEncodedSurroundMode = newSurroundMode;
}
}
}
diff --git a/services/core/java/com/android/server/camera/CameraService.java b/services/core/java/com/android/server/camera/CameraService.java
index f82454a..cd8eb4e 100644
--- a/services/core/java/com/android/server/camera/CameraService.java
+++ b/services/core/java/com/android/server/camera/CameraService.java
@@ -60,10 +60,6 @@
public static final String CAMERA_SERVICE_PROXY_BINDER_NAME = "media.camera.proxy";
- // Event arguments to use with the camera service notifySystemEvent call:
- public static final int NO_EVENT = 0; // NOOP
- public static final int USER_SWITCHED = 1; // User changed, argument is the new user handle
-
// State arguments to use with the notifyCameraState call from camera service:
public static final int CAMERA_STATE_OPEN = 0;
public static final int CAMERA_STATE_ACTIVE = 1;
@@ -224,7 +220,7 @@
if (mEnabledCameraUsers == null || !mEnabledCameraUsers.equals(currentUserHandles)) {
// Some user handles have been added or removed, update mediaserver.
mEnabledCameraUsers = currentUserHandles;
- notifyMediaserverLocked(USER_SWITCHED, currentUserHandles);
+ notifyMediaserverLocked(ICameraService.EVENT_USER_SWITCHED, currentUserHandles);
}
}
@@ -244,7 +240,7 @@
if (mEnabledCameraUsers == null) {
return;
}
- if (notifyMediaserverLocked(USER_SWITCHED, mEnabledCameraUsers)) {
+ if (notifyMediaserverLocked(ICameraService.EVENT_USER_SWITCHED, mEnabledCameraUsers)) {
retries = 0;
}
}
diff --git a/services/core/java/com/android/server/connectivity/ApfFilter.java b/services/core/java/com/android/server/connectivity/ApfFilter.java
new file mode 100644
index 0000000..25c84e1
--- /dev/null
+++ b/services/core/java/com/android/server/connectivity/ApfFilter.java
@@ -0,0 +1,499 @@
+/*
+ * 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.
+ */
+
+package com.android.server.connectivity;
+
+import static android.system.OsConstants.*;
+
+import android.net.NetworkUtils;
+import android.net.apf.ApfGenerator;
+import android.net.apf.ApfGenerator.IllegalInstructionException;
+import android.net.apf.ApfGenerator.Register;
+import android.system.ErrnoException;
+import android.system.Os;
+import android.system.PacketSocketAddress;
+import android.util.Log;
+import android.util.Pair;
+
+import com.android.internal.util.HexDump;
+import com.android.server.ConnectivityService;
+
+import java.io.FileDescriptor;
+import java.io.IOException;
+import java.lang.Thread;
+import java.net.NetworkInterface;
+import java.net.SocketException;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.Arrays;
+
+import libcore.io.IoBridge;
+
+/**
+ * For networks that support packet filtering via APF programs, {@code ApfFilter}
+ * listens for IPv6 ICMPv6 router advertisements (RAs) and generates APF programs to
+ * filter out redundant duplicate ones.
+ *
+ * @hide
+ */
+public class ApfFilter {
+ // Thread to listen for RAs.
+ private class ReceiveThread extends Thread {
+ private final byte[] mPacket = new byte[1514];
+ private final FileDescriptor mSocket;
+ private volatile boolean mStopped;
+
+ public ReceiveThread(FileDescriptor socket) {
+ mSocket = socket;
+ }
+
+ public void halt() {
+ mStopped = true;
+ try {
+ // Interrupts the read() call the thread is blocked in.
+ IoBridge.closeAndSignalBlockedThreads(mSocket);
+ } catch (IOException ignored) {}
+ }
+
+ @Override
+ public void run() {
+ log("begin monitoring");
+ while (!mStopped) {
+ try {
+ int length = Os.read(mSocket, mPacket, 0, mPacket.length);
+ processRa(mPacket, length);
+ } catch (IOException|ErrnoException e) {
+ if (!mStopped) {
+ Log.e(TAG, "Read error", e);
+ }
+ }
+ }
+ }
+ }
+
+ private static final String TAG = "ApfFilter";
+
+ private final ConnectivityService mConnectivityService;
+ private final NetworkAgentInfo mNai;
+ private ReceiveThread mReceiveThread;
+ private String mIfaceName;
+ private long mUniqueCounter;
+
+ private ApfFilter(ConnectivityService connectivityService, NetworkAgentInfo nai) {
+ mConnectivityService = connectivityService;
+ mNai = nai;
+ maybeStartFilter();
+ }
+
+ private void log(String s) {
+ Log.d(TAG, "(" + mNai.network.netId + "): " + s);
+ }
+
+ private long getUniqueNumber() {
+ return mUniqueCounter++;
+ }
+
+ /**
+ * Attempt to start listening for RAs and, if RAs are received, generating and installing
+ * filters to ignore useless RAs.
+ */
+ private void maybeStartFilter() {
+ mIfaceName = mNai.linkProperties.getInterfaceName();
+ if (mIfaceName == null) return;
+ FileDescriptor socket;
+ try {
+ socket = Os.socket(AF_PACKET, SOCK_RAW, ETH_P_IPV6);
+ PacketSocketAddress addr = new PacketSocketAddress((short) ETH_P_IPV6,
+ NetworkInterface.getByName(mIfaceName).getIndex());
+ Os.bind(socket, addr);
+ NetworkUtils.attachRaFilter(socket, mNai.networkMisc.apfPacketFormat);
+ } catch(SocketException|ErrnoException e) {
+ Log.e(TAG, "Error filtering raw socket", e);
+ return;
+ }
+ mReceiveThread = new ReceiveThread(socket);
+ mReceiveThread.start();
+ }
+
+ /**
+ * mNai's LinkProperties may have changed, take appropriate action.
+ */
+ public void updateFilter() {
+ // If we're not listening for RAs, try starting.
+ if (mReceiveThread == null) {
+ maybeStartFilter();
+ // If interface name has changed, restart.
+ } else if (!mIfaceName.equals(mNai.linkProperties.getInterfaceName())) {
+ shutdown();
+ maybeStartFilter();
+ }
+ }
+
+ // Returns seconds since Unix Epoch.
+ private static long curTime() {
+ return System.currentTimeMillis() / 1000L;
+ }
+
+ // A class to hold information about an RA.
+ private class Ra {
+ private static final int ETH_HEADER_LEN = 14;
+
+ private static final int IPV6_HEADER_LEN = 40;
+
+ // From RFC4861:
+ private static final int ICMP6_RA_HEADER_LEN = 16;
+ private static final int ICMP6_RA_OPTION_OFFSET =
+ ETH_HEADER_LEN + IPV6_HEADER_LEN + ICMP6_RA_HEADER_LEN;
+ private static final int ICMP6_RA_ROUTER_LIFETIME_OFFSET =
+ ETH_HEADER_LEN + IPV6_HEADER_LEN + 6;
+ private static final int ICMP6_RA_ROUTER_LIFETIME_LEN = 2;
+ // Prefix information option.
+ private static final int ICMP6_PREFIX_OPTION_TYPE = 3;
+ private static final int ICMP6_PREFIX_OPTION_LEN = 32;
+ private static final int ICMP6_PREFIX_OPTION_VALID_LIFETIME_OFFSET = 4;
+ private static final int ICMP6_PREFIX_OPTION_VALID_LIFETIME_LEN = 4;
+ private static final int ICMP6_PREFIX_OPTION_PREFERRED_LIFETIME_OFFSET = 8;
+ private static final int ICMP6_PREFIX_OPTION_PREFERRED_LIFETIME_LEN = 4;
+
+ // From RFC6106: Recursive DNS Server option
+ private static final int ICMP6_RDNSS_OPTION_TYPE = 25;
+ // From RFC6106: DNS Search List option
+ private static final int ICMP6_DNSSL_OPTION_TYPE = 31;
+
+ // From RFC4191: Route Information option
+ private static final int ICMP6_ROUTE_INFO_OPTION_TYPE = 24;
+ // Above three options all have the same format:
+ private static final int ICMP6_4_BYTE_LIFETIME_OFFSET = 4;
+ private static final int ICMP6_4_BYTE_LIFETIME_LEN = 4;
+
+ private final ByteBuffer mPacket;
+ // List of binary ranges that include the whole packet except the lifetimes.
+ // Pairs consist of offset and length.
+ private final ArrayList<Pair<Integer, Integer>> mNonLifetimes =
+ new ArrayList<Pair<Integer, Integer>>();
+ // Minimum lifetime in packet
+ long mMinLifetime;
+ // When the packet was last captured, in seconds since Unix Epoch
+ long mLastSeen;
+
+ /**
+ * Add a binary range of the packet that does not include a lifetime to mNonLifetimes.
+ * Assumes mPacket.position() is as far as we've parsed the packet.
+ * @param lastNonLifetimeStart offset within packet of where the last binary range of
+ * data not including a lifetime.
+ * @param lifetimeOffset offset from mPacket.position() to the next lifetime data.
+ * @param lifetimeLength length of the next lifetime data.
+ * @return offset within packet of where the next binary range of data not including
+ * a lifetime. This can be passed into the next invocation of this function
+ * via {@code lastNonLifetimeStart}.
+ */
+ private int addNonLifetime(int lastNonLifetimeStart, int lifetimeOffset,
+ int lifetimeLength) {
+ lifetimeOffset += mPacket.position();
+ mNonLifetimes.add(new Pair<Integer, Integer>(lastNonLifetimeStart,
+ lifetimeOffset - lastNonLifetimeStart));
+ return lifetimeOffset + lifetimeLength;
+ }
+
+ // Note that this parses RA and may throw IllegalArgumentException (from
+ // Buffer.position(int) ) or IndexOutOfBoundsException (from ByteBuffer.get(int) ) if
+ // parsing encounters something non-compliant with specifications.
+ Ra(byte[] packet, int length) {
+ mPacket = ByteBuffer.allocate(length).put(ByteBuffer.wrap(packet, 0, length));
+ mPacket.clear();
+ mLastSeen = curTime();
+
+ // Parse router lifetime
+ int lastNonLifetimeStart = addNonLifetime(0, ICMP6_RA_ROUTER_LIFETIME_OFFSET,
+ ICMP6_RA_ROUTER_LIFETIME_LEN);
+ // Parse ICMP6 options
+ mPacket.position(ICMP6_RA_OPTION_OFFSET);
+ while (mPacket.hasRemaining()) {
+ int optionType = ((int)mPacket.get(mPacket.position())) & 0xff;
+ int optionLength = (((int)mPacket.get(mPacket.position() + 1)) & 0xff) * 8;
+ switch (optionType) {
+ case ICMP6_PREFIX_OPTION_TYPE:
+ // Parse valid lifetime
+ lastNonLifetimeStart = addNonLifetime(lastNonLifetimeStart,
+ ICMP6_PREFIX_OPTION_VALID_LIFETIME_OFFSET,
+ ICMP6_PREFIX_OPTION_VALID_LIFETIME_LEN);
+ // Parse preferred lifetime
+ lastNonLifetimeStart = addNonLifetime(lastNonLifetimeStart,
+ ICMP6_PREFIX_OPTION_PREFERRED_LIFETIME_OFFSET,
+ ICMP6_PREFIX_OPTION_PREFERRED_LIFETIME_LEN);
+ break;
+ // These three options have the same lifetime offset and size, so process
+ // together:
+ case ICMP6_ROUTE_INFO_OPTION_TYPE:
+ case ICMP6_RDNSS_OPTION_TYPE:
+ case ICMP6_DNSSL_OPTION_TYPE:
+ // Parse lifetime
+ lastNonLifetimeStart = addNonLifetime(lastNonLifetimeStart,
+ ICMP6_4_BYTE_LIFETIME_OFFSET,
+ ICMP6_4_BYTE_LIFETIME_LEN);
+ break;
+ default:
+ // RFC4861 section 4.2 dictates we ignore unknown options for fowards
+ // compatibility.
+ break;
+ }
+ mPacket.position(mPacket.position() + optionLength);
+ }
+ // Mark non-lifetime bytes since last lifetime.
+ addNonLifetime(lastNonLifetimeStart, 0, 0);
+ mMinLifetime = minLifetime(packet, length);
+ }
+
+ // Ignoring lifetimes (which may change) does {@code packet} match this RA?
+ boolean matches(byte[] packet, int length) {
+ if (length != mPacket.limit()) return false;
+ ByteBuffer a = ByteBuffer.wrap(packet);
+ ByteBuffer b = mPacket;
+ for (Pair<Integer, Integer> nonLifetime : mNonLifetimes) {
+ a.clear();
+ b.clear();
+ a.position(nonLifetime.first);
+ b.position(nonLifetime.first);
+ a.limit(nonLifetime.first + nonLifetime.second);
+ b.limit(nonLifetime.first + nonLifetime.second);
+ if (a.compareTo(b) != 0) return false;
+ }
+ return true;
+ }
+
+ // What is the minimum of all lifetimes within {@code packet} in seconds?
+ // Precondition: matches(packet, length) already returned true.
+ long minLifetime(byte[] packet, int length) {
+ long minLifetime = Long.MAX_VALUE;
+ // Wrap packet in ByteBuffer so we can read big-endian values easily
+ ByteBuffer byteBuffer = ByteBuffer.wrap(packet);
+ for (int i = 0; (i + 1) < mNonLifetimes.size(); i++) {
+ int offset = mNonLifetimes.get(i).first + mNonLifetimes.get(i).second;
+ int lifetimeLength = mNonLifetimes.get(i+1).first - offset;
+ long val;
+ switch (lifetimeLength) {
+ case 2: val = byteBuffer.getShort(offset); break;
+ case 4: val = byteBuffer.getInt(offset); break;
+ default: throw new IllegalStateException("bogus lifetime size " + length);
+ }
+ // Mask to size, converting signed to unsigned
+ val &= (1L << (lifetimeLength * 8)) - 1;
+ minLifetime = Math.min(minLifetime, val);
+ }
+ return minLifetime;
+ }
+
+ // How many seconds does this RA's have to live, taking into account the fact
+ // that we might have seen it a while ago.
+ long currentLifetime() {
+ return mMinLifetime - (curTime() - mLastSeen);
+ }
+
+ boolean isExpired() {
+ return currentLifetime() < 0;
+ }
+
+ // Append a filter for this RA to {@code gen}. Jump to DROP_LABEL if it should be dropped.
+ // Jump to the next filter if packet doesn't match this RA.
+ long generateFilter(ApfGenerator gen) throws IllegalInstructionException {
+ String nextFilterLabel = "Ra" + getUniqueNumber();
+ // Skip if packet is not the right size
+ gen.addLoadFromMemory(Register.R0, gen.PACKET_SIZE_MEMORY_SLOT);
+ gen.addJumpIfR0NotEquals(mPacket.limit(), nextFilterLabel);
+ int filterLifetime = (int)(currentLifetime() / FRACTION_OF_LIFETIME_TO_FILTER);
+ // Skip filter if expired
+ gen.addLoadFromMemory(Register.R0, gen.FILTER_AGE_MEMORY_SLOT);
+ gen.addJumpIfR0GreaterThan(filterLifetime, nextFilterLabel);
+ for (int i = 0; i < mNonLifetimes.size(); i++) {
+ // Generate code to match the packet bytes
+ Pair<Integer, Integer> nonLifetime = mNonLifetimes.get(i);
+ gen.addLoadImmediate(Register.R0, nonLifetime.first);
+ gen.addJumpIfBytesNotEqual(Register.R0,
+ Arrays.copyOfRange(mPacket.array(), nonLifetime.first,
+ nonLifetime.first + nonLifetime.second),
+ nextFilterLabel);
+ // Generate code to test the lifetimes haven't gone down too far
+ if ((i + 1) < mNonLifetimes.size()) {
+ Pair<Integer, Integer> nextNonLifetime = mNonLifetimes.get(i + 1);
+ int offset = nonLifetime.first + nonLifetime.second;
+ int length = nextNonLifetime.first - offset;
+ switch (length) {
+ case 4: gen.addLoad32(Register.R0, offset); break;
+ case 2: gen.addLoad16(Register.R0, offset); break;
+ default: throw new IllegalStateException("bogus lifetime size " + length);
+ }
+ gen.addJumpIfR0LessThan(filterLifetime, nextFilterLabel);
+ }
+ }
+ gen.addJump(gen.DROP_LABEL);
+ gen.defineLabel(nextFilterLabel);
+ return filterLifetime;
+ }
+ }
+
+ // Maximum number of RAs to filter for.
+ private static final int MAX_RAS = 10;
+ private ArrayList<Ra> mRas = new ArrayList<Ra>();
+
+ // There is always some marginal benefit to updating the installed APF program when an RA is
+ // seen because we can extend the program's lifetime slightly, but there is some cost to
+ // updating the program, so don't bother unless the program is going to expire soon. This
+ // constant defines "soon" in seconds.
+ private static final long MAX_PROGRAM_LIFETIME_WORTH_REFRESHING = 30;
+ // We don't want to filter an RA for it's whole lifetime as it'll be expired by the time we ever
+ // see a refresh. Using half the lifetime might be a good idea except for the fact that
+ // packets may be dropped, so let's use 6.
+ private static final int FRACTION_OF_LIFETIME_TO_FILTER = 6;
+
+ // When did we last install a filter program? In seconds since Unix Epoch.
+ private long mLastTimeInstalledProgram;
+ // How long should the last installed filter program live for? In seconds.
+ private long mLastInstalledProgramMinLifetime;
+
+ private void installNewProgram() {
+ if (mRas.size() == 0) return;
+ final byte[] program;
+ long programMinLifetime = Long.MAX_VALUE;
+ try {
+ ApfGenerator gen = new ApfGenerator();
+ // This is guaranteed to return true because of the check in maybeInstall.
+ gen.setApfVersion(mNai.networkMisc.apfVersionSupported);
+ // Step 1: Determine how many RA filters we can fit in the program.
+ int ras = 0;
+ for (Ra ra : mRas) {
+ if (ra.isExpired()) continue;
+ ra.generateFilter(gen);
+ if (gen.programLengthOverEstimate() > mNai.networkMisc.maximumApfProgramSize) {
+ // We went too far. Use prior number of RAs in "ras".
+ break;
+ } else {
+ // Yay! this RA filter fits, increment "ras".
+ ras++;
+ }
+ }
+ // Step 2: Generate RA filters
+ gen = new ApfGenerator();
+ // This is guaranteed to return true because of the check in maybeInstall.
+ gen.setApfVersion(mNai.networkMisc.apfVersionSupported);
+ for (Ra ra : mRas) {
+ if (ras-- == 0) break;
+ if (ra.isExpired()) continue;
+ programMinLifetime = Math.min(programMinLifetime, ra.generateFilter(gen));
+ }
+ // Execution will reach the end of the program if no filters match, which will pass the
+ // packet to the AP.
+ program = gen.generate();
+ } catch (IllegalInstructionException e) {
+ Log.e(TAG, "Program failed to generate: ", e);
+ return;
+ }
+ mLastTimeInstalledProgram = curTime();
+ mLastInstalledProgramMinLifetime = programMinLifetime;
+ hexDump("Installing filter: ", program, program.length);
+ mConnectivityService.pushApfProgramToNetwork(mNai, program);
+ }
+
+ // Install a new filter program if the last installed one will die soon.
+ private void maybeInstallNewProgram() {
+ if (mRas.size() == 0) return;
+ // If the current program doesn't expire for a while, don't bother updating.
+ long expiry = mLastTimeInstalledProgram + mLastInstalledProgramMinLifetime;
+ if (expiry < curTime() + MAX_PROGRAM_LIFETIME_WORTH_REFRESHING) {
+ installNewProgram();
+ }
+ }
+
+ private void hexDump(String msg, byte[] packet, int length) {
+ log(msg + HexDump.toHexString(packet, 0, length));
+ }
+
+ private void processRa(byte[] packet, int length) {
+ hexDump("Read packet = ", packet, length);
+
+ // Have we seen this RA before?
+ for (int i = 0; i < mRas.size(); i++) {
+ Ra ra = mRas.get(i);
+ if (ra.matches(packet, length)) {
+ log("matched RA");
+ // Update lifetimes.
+ ra.mLastSeen = curTime();
+ ra.mMinLifetime = ra.minLifetime(packet, length);
+
+ // Keep mRas in LRU order so as to prioritize generating filters for recently seen
+ // RAs. LRU prioritizes this because RA filters are generated in order from mRas
+ // until the filter program exceeds the maximum filter program size allowed by the
+ // chipset, so RAs appearing earlier in mRas are more likely to make it into the
+ // filter program.
+ // TODO: consider sorting the RAs in order of increasing expiry time as well.
+ // Swap to front of array.
+ mRas.add(0, mRas.remove(i));
+
+ maybeInstallNewProgram();
+ return;
+ }
+ }
+ // Purge expired RAs.
+ for (int i = 0; i < mRas.size();) {
+ if (mRas.get(i).isExpired()) {
+ log("expired RA");
+ mRas.remove(i);
+ } else {
+ i++;
+ }
+ }
+ // TODO: figure out how to proceed when we've received more then MAX_RAS RAs.
+ if (mRas.size() >= MAX_RAS) return;
+ try {
+ log("adding RA");
+ mRas.add(new Ra(packet, length));
+ } catch (Exception e) {
+ Log.e(TAG, "Error parsing RA: " + e);
+ return;
+ }
+ installNewProgram();
+ }
+
+ /**
+ * Install an {@link ApfFilter} on {@code nai} if {@code nai} supports packet
+ * filtering using APF programs.
+ */
+ public static void maybeInstall(ConnectivityService connectivityService, NetworkAgentInfo nai) {
+ if (nai.networkMisc == null) return;
+ if (nai.networkMisc.apfVersionSupported == 0) return;
+ if (nai.networkMisc.maximumApfProgramSize < 200) {
+ Log.e(TAG, "Uselessly small APF size limit: " + nai.networkMisc.maximumApfProgramSize);
+ return;
+ }
+ // For now only support generating programs for Ethernet frames. If this restriction is
+ // lifted:
+ // 1. the program generator will need its offsets adjusted.
+ // 2. the packet filter attached to our packet socket will need its offset adjusted.
+ if (nai.networkMisc.apfPacketFormat != ARPHRD_ETHER) return;
+ if (!new ApfGenerator().setApfVersion(nai.networkMisc.apfVersionSupported)) {
+ Log.e(TAG, "Unsupported APF version: " + nai.networkMisc.apfVersionSupported);
+ return;
+ }
+ nai.apfFilter = new ApfFilter(connectivityService, nai);
+ }
+
+ public void shutdown() {
+ if (mReceiveThread != null) {
+ log("shuting down");
+ mReceiveThread.halt(); // Also closes socket.
+ mReceiveThread = null;
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/connectivity/Nat464Xlat.java b/services/core/java/com/android/server/connectivity/Nat464Xlat.java
index a9eaeee..b390884 100644
--- a/services/core/java/com/android/server/connectivity/Nat464Xlat.java
+++ b/services/core/java/com/android/server/connectivity/Nat464Xlat.java
@@ -16,13 +16,11 @@
package com.android.server.connectivity;
-import static android.net.ConnectivityManager.TYPE_MOBILE;
-import static android.net.ConnectivityManager.TYPE_WIFI;
-
import java.net.Inet4Address;
import android.content.Context;
import android.net.InterfaceConfiguration;
+import android.net.ConnectivityManager;
import android.net.LinkAddress;
import android.net.LinkProperties;
import android.net.NetworkAgent;
@@ -34,6 +32,7 @@
import android.util.Slog;
import com.android.server.net.BaseNetworkObserver;
+import com.android.internal.util.ArrayUtils;
/**
* @hide
@@ -46,6 +45,13 @@
// This must match the interface prefix in clatd.c.
private static final String CLAT_PREFIX = "v4-";
+ // The network types we will start clatd on.
+ private static final int[] NETWORK_TYPES = {
+ ConnectivityManager.TYPE_MOBILE,
+ ConnectivityManager.TYPE_WIFI,
+ ConnectivityManager.TYPE_ETHERNET,
+ };
+
private final INetworkManagementService mNMService;
// ConnectivityService Handler for LinkProperties updates.
@@ -90,7 +96,7 @@
(nai.linkProperties != null) ? nai.linkProperties.hasIPv4Address() : false;
// Only support clat on mobile and wifi for now, because these are the only IPv6-only
// networks we can connect to.
- return connected && !hasIPv4Address && (netType == TYPE_MOBILE || netType == TYPE_WIFI);
+ return connected && !hasIPv4Address && ArrayUtils.contains(NETWORK_TYPES, netType);
}
/**
@@ -221,7 +227,7 @@
}
private void maybeSetIpv6NdOffload(String iface, boolean on) {
- if (mNetwork.networkInfo.getType() != TYPE_WIFI) {
+ if (mNetwork.networkInfo.getType() != ConnectivityManager.TYPE_WIFI) {
return;
}
try {
diff --git a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
index c5d38cb..b4c71c1 100644
--- a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
+++ b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
@@ -32,6 +32,7 @@
import com.android.internal.util.AsyncChannel;
import com.android.server.ConnectivityService;
import com.android.server.connectivity.NetworkMonitor;
+import com.android.server.connectivity.ApfFilter;
import java.util.ArrayList;
import java.util.Comparator;
@@ -163,6 +164,8 @@
// Used by ConnectivityService to keep track of 464xlat.
public Nat464Xlat clatd;
+ public ApfFilter apfFilter;
+
public NetworkAgentInfo(Messenger messenger, AsyncChannel ac, Network net, NetworkInfo info,
LinkProperties lp, NetworkCapabilities nc, int score, Context context, Handler handler,
NetworkMisc misc, NetworkRequest defaultRequest, ConnectivityService connService) {
@@ -175,6 +178,7 @@
currentScore = score;
networkMonitor = connService.createNetworkMonitor(context, handler, this, defaultRequest);
networkMisc = misc;
+ apfFilter.maybeInstall(connService, this);
}
/**
diff --git a/services/core/java/com/android/server/connectivity/NetworkMonitor.java b/services/core/java/com/android/server/connectivity/NetworkMonitor.java
index 4504bdb..fb8b110 100644
--- a/services/core/java/com/android/server/connectivity/NetworkMonitor.java
+++ b/services/core/java/com/android/server/connectivity/NetworkMonitor.java
@@ -566,7 +566,7 @@
@Override
public void enter() {
final String cmdName = ACTION_LINGER_EXPIRED + "." + mNetworkAgentInfo.network.netId;
- mWakeupMessage = new WakeupMessage(mContext, getHandler(), cmdName, CMD_LINGER_EXPIRED);
+ mWakeupMessage = makeWakeupMessage(mContext, getHandler(), cmdName, CMD_LINGER_EXPIRED);
long wakeupTime = SystemClock.elapsedRealtime() + mLingerDelayMs;
mWakeupMessage.schedule(wakeupTime);
}
@@ -823,4 +823,9 @@
}
DEFAULT_LINGER_DELAY_MS = time_ms;
}
+
+ @VisibleForTesting
+ protected WakeupMessage makeWakeupMessage(Context c, Handler h, String s, int i) {
+ return new WakeupMessage(c, h, s, i);
+ }
}
diff --git a/services/core/java/com/android/server/location/GnssLocationProvider.java b/services/core/java/com/android/server/location/GnssLocationProvider.java
index ed68abe..e08fad4 100644
--- a/services/core/java/com/android/server/location/GnssLocationProvider.java
+++ b/services/core/java/com/android/server/location/GnssLocationProvider.java
@@ -1559,11 +1559,11 @@
* called from native code to update SV info
*/
private void reportSvStatus() {
- int svCount = native_read_sv_status(mSvidWithFlags, mSnrs, mSvElevations, mSvAzimuths);
+ int svCount = native_read_sv_status(mSvidWithFlags, mCn0s, mSvElevations, mSvAzimuths);
mListenerHelper.onSvStatusChanged(
svCount,
mSvidWithFlags,
- mSnrs,
+ mCn0s,
mSvElevations,
mSvAzimuths);
@@ -1578,7 +1578,7 @@
}
if (VERBOSE) {
Log.v(TAG, "svid: " + (mSvidWithFlags[i] >> GnssStatus.SVID_SHIFT_WIDTH) +
- " snr: " + mSnrs[i]/10 +
+ " cn0: " + mCn0s[i]/10 +
" elev: " + mSvElevations[i] +
" azimuth: " + mSvAzimuths[i] +
((mSvidWithFlags[i] & GnssStatus.GNSS_SV_FLAGS_HAS_EPHEMERIS_DATA) == 0
@@ -2402,7 +2402,7 @@
// preallocated arrays, to avoid memory allocation in reportStatus()
private int mSvidWithFlags[] = new int[MAX_SVS];
- private float mSnrs[] = new float[MAX_SVS];
+ private float mCn0s[] = new float[MAX_SVS];
private float mSvElevations[] = new float[MAX_SVS];
private float mSvAzimuths[] = new float[MAX_SVS];
private int mSvCount;
@@ -2424,7 +2424,7 @@
private native void native_delete_aiding_data(int flags);
// returns number of SVs
// mask[0] is ephemeris mask and mask[1] is almanac mask
- private native int native_read_sv_status(int[] prnWithFlags, float[] snrs, float[] elevations,
+ private native int native_read_sv_status(int[] prnWithFlags, float[] cn0s, float[] elevations,
float[] azimuths);
private native int native_read_nmea(byte[] buffer, int bufferSize);
private native void native_inject_location(double latitude, double longitude, float accuracy);
diff --git a/services/core/java/com/android/server/location/GnssMeasurementsProvider.java b/services/core/java/com/android/server/location/GnssMeasurementsProvider.java
index d9e8e91..734a8d4 100644
--- a/services/core/java/com/android/server/location/GnssMeasurementsProvider.java
+++ b/services/core/java/com/android/server/location/GnssMeasurementsProvider.java
@@ -72,7 +72,7 @@
status = GnssMeasurementsEvent.STATUS_NOT_SUPPORTED;
break;
case RESULT_GPS_LOCATION_DISABLED:
- status = GnssMeasurementsEvent.STATUS_GPS_LOCATION_DISABLED;
+ status = GnssMeasurementsEvent.STATUS_GNSS_LOCATION_DISABLED;
break;
case RESULT_UNKNOWN:
return null;
diff --git a/services/core/java/com/android/server/location/GnssNavigationMessageProvider.java b/services/core/java/com/android/server/location/GnssNavigationMessageProvider.java
index 57bce4b..fdef31f 100644
--- a/services/core/java/com/android/server/location/GnssNavigationMessageProvider.java
+++ b/services/core/java/com/android/server/location/GnssNavigationMessageProvider.java
@@ -73,7 +73,8 @@
status = GnssNavigationMessageEvent.STATUS_NOT_SUPPORTED;
break;
case RESULT_GPS_LOCATION_DISABLED:
- status = GnssNavigationMessageEvent.STATUS_GPS_LOCATION_DISABLED;
+ status = GnssNavigationMessageEvent
+ .STATUS_GNSS_LOCATION_DISABLED;
break;
case RESULT_UNKNOWN:
return null;
diff --git a/services/core/java/com/android/server/location/GnssStatusListenerHelper.java b/services/core/java/com/android/server/location/GnssStatusListenerHelper.java
index 0b3111c..d471e45 100644
--- a/services/core/java/com/android/server/location/GnssStatusListenerHelper.java
+++ b/services/core/java/com/android/server/location/GnssStatusListenerHelper.java
@@ -75,7 +75,7 @@
public void onSvStatusChanged(
final int svCount,
final int[] prnWithFlags,
- final float[] snrs,
+ final float[] cn0s,
final float[] elevations,
final float[] azimuths) {
Operation operation = new Operation() {
@@ -84,7 +84,7 @@
listener.onSvStatusChanged(
svCount,
prnWithFlags,
- snrs,
+ cn0s,
elevations,
azimuths);
}
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index 9a9ca79..2900345 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -42,6 +42,7 @@
import static android.net.NetworkPolicy.WARNING_DISABLED;
import static android.net.NetworkPolicyManager.EXTRA_NETWORK_TEMPLATE;
import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_DOZABLE;
+import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_POWERSAVE;
import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_STANDBY;
import static android.net.NetworkPolicyManager.FIREWALL_RULE_ALLOW;
import static android.net.NetworkPolicyManager.FIREWALL_RULE_DEFAULT;
@@ -295,6 +296,7 @@
final SparseIntArray mUidFirewallStandbyRules = new SparseIntArray();
final SparseIntArray mUidFirewallDozableRules = new SparseIntArray();
+ final SparseIntArray mUidFirewallPowerSaveRules = new SparseIntArray();
/** Set of states for the child firewall chains. True if the chain is active. */
final SparseBooleanArray mFirewallChainStates = new SparseBooleanArray();
@@ -523,9 +525,11 @@
new PowerManagerInternal.LowPowerModeListener() {
@Override
public void onLowPowerModeChanged(boolean enabled) {
+ if (LOGD) Slog.d(TAG, "onLowPowerModeChanged(" + enabled + ")");
synchronized (mRulesLock) {
if (mRestrictPower != enabled) {
mRestrictPower = enabled;
+ updateRulesForRestrictPowerLocked();
updateRulesForGlobalChangeLocked(true);
}
}
@@ -1176,13 +1180,6 @@
return;
}
- // If we are in restrict power mode, we want to treat all interfaces
- // as metered, to restrict access to the network by uid. However, we
- // will not have a bandwidth limit. Also only do this if restrict
- // background data use is *not* enabled, since that takes precedence
- // use over those networks can have a cost associated with it).
- final boolean powerSave = mRestrictPower && !mRestrictBackground;
-
// First, generate identities of all connected networks so we can
// quickly compare them against all defined policies below.
final ArrayList<Pair<String, NetworkIdentity>> connIdents = new ArrayList<>(states.length);
@@ -1194,9 +1191,6 @@
final String baseIface = state.linkProperties.getInterfaceName();
if (baseIface != null) {
connIdents.add(Pair.create(baseIface, ident));
- if (powerSave) {
- connIfaces.add(baseIface);
- }
}
// Stacked interfaces are considered to have same identity as
@@ -1206,9 +1200,6 @@
final String stackedIface = stackedLink.getInterfaceName();
if (stackedIface != null) {
connIdents.add(Pair.create(stackedIface, ident));
- if (powerSave) {
- connIfaces.add(stackedIface);
- }
}
}
}
@@ -1286,9 +1277,6 @@
removeInterfaceQuota(iface);
setInterfaceQuota(iface, quotaBytes);
newMeteredIfaces.add(iface);
- if (powerSave) {
- connIfaces.remove(iface);
- }
}
}
@@ -2299,9 +2287,14 @@
// state changed, push updated rules
mUidState.put(uid, uidState);
updateRulesForUidStateChangeLocked(uid, oldUidState, uidState);
- if (mDeviceIdleMode && isProcStateAllowedWhileIdle(oldUidState)
- != isProcStateAllowedWhileIdle(uidState)) {
- updateRuleForDeviceIdleLocked(uid);
+ if (isProcStateAllowedWhileIdleOrPowerSaveMode(oldUidState)
+ != isProcStateAllowedWhileIdleOrPowerSaveMode(uidState) ) {
+ if (mDeviceIdleMode) {
+ updateRuleForDeviceIdleLocked(uid);
+ }
+ if (mRestrictPower) {
+ updateRulesForRestrictPowerLocked(uid);
+ }
}
}
}
@@ -2317,6 +2310,9 @@
if (mDeviceIdleMode) {
updateRuleForDeviceIdleLocked(uid);
}
+ if (mRestrictPower) {
+ updateRulesForRestrictPowerLocked(uid);
+ }
}
}
}
@@ -2354,15 +2350,36 @@
}
}
- static boolean isProcStateAllowedWhileIdle(int procState) {
+ static boolean isProcStateAllowedWhileIdleOrPowerSaveMode(int procState) {
return procState <= ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE;
}
+ void updateRulesForRestrictPowerLocked() {
+ updateRulesForWhitelistedPowerSaveLocked(mRestrictPower, FIREWALL_CHAIN_POWERSAVE,
+ mUidFirewallPowerSaveRules);
+ }
+
+ void updateRulesForRestrictPowerLocked(int uid) {
+ updateRulesForWhitelistedPowerSaveLocked(uid, mRestrictPower, FIREWALL_CHAIN_POWERSAVE);
+ }
+
void updateRulesForDeviceIdleLocked() {
- if (mDeviceIdleMode) {
- // sync the whitelists before enable dozable chain. We don't care about the rules if
+ updateRulesForWhitelistedPowerSaveLocked(mDeviceIdleMode, FIREWALL_CHAIN_DOZABLE,
+ mUidFirewallDozableRules);
+ }
+
+ void updateRuleForDeviceIdleLocked(int uid) {
+ updateRulesForWhitelistedPowerSaveLocked(uid, mDeviceIdleMode, FIREWALL_CHAIN_DOZABLE);
+ }
+
+ // NOTE: since both fw_dozable and fw_powersave uses the same map (mPowerSaveTempWhitelistAppIds)
+ // for whitelisting, we can reuse their logic in this method.
+ private void updateRulesForWhitelistedPowerSaveLocked(boolean enabled, int chain,
+ SparseIntArray rules) {
+ if (enabled) {
+ // Sync the whitelists before enabling the chain. We don't care about the rules if
// we are disabling the chain.
- final SparseIntArray uidRules = mUidFirewallDozableRules;
+ final SparseIntArray uidRules = rules;
uidRules.clear();
final List<UserInfo> users = mUserManager.getUsers();
for (int ui = users.size() - 1; ui >= 0; ui--) {
@@ -2381,24 +2398,26 @@
}
}
for (int i = mUidState.size() - 1; i >= 0; i--) {
- if (isProcStateAllowedWhileIdle(mUidState.valueAt(i))) {
+ if (isProcStateAllowedWhileIdleOrPowerSaveMode(mUidState.valueAt(i))) {
uidRules.put(mUidState.keyAt(i), FIREWALL_RULE_ALLOW);
}
}
- setUidFirewallRules(FIREWALL_CHAIN_DOZABLE, uidRules);
+ setUidFirewallRules(chain, uidRules);
}
- enableFirewallChainLocked(FIREWALL_CHAIN_DOZABLE, mDeviceIdleMode);
+ enableFirewallChainLocked(chain, enabled);
}
- void updateRuleForDeviceIdleLocked(int uid) {
- if (mDeviceIdleMode) {
+ // NOTE: since both fw_dozable and fw_powersave uses the same map (mPowerSaveTempWhitelistAppIds)
+ // for whitelisting, we can reuse their logic in this method.
+ private void updateRulesForWhitelistedPowerSaveLocked(int uid, boolean enabled, int chain) {
+ if (enabled) {
int appId = UserHandle.getAppId(uid);
if (mPowerSaveTempWhitelistAppIds.get(appId) || mPowerSaveWhitelistAppIds.get(appId)
- || isProcStateAllowedWhileIdle(mUidState.get(uid))) {
- setUidFirewallRule(FIREWALL_CHAIN_DOZABLE, uid, FIREWALL_RULE_ALLOW);
+ || isProcStateAllowedWhileIdleOrPowerSaveMode(mUidState.get(uid))) {
+ setUidFirewallRule(chain, uid, FIREWALL_RULE_ALLOW);
} else {
- setUidFirewallRule(FIREWALL_CHAIN_DOZABLE, uid, FIREWALL_RULE_DEFAULT);
+ setUidFirewallRule(chain, uid, FIREWALL_RULE_DEFAULT);
}
}
@@ -2461,6 +2480,7 @@
updateRulesForDeviceIdleLocked();
updateRulesForAppIdleLocked();
+ updateRulesForRestrictPowerLocked();
// update rules for all installed applications
final List<UserInfo> users = mUserManager.getUsers();
@@ -2504,6 +2524,7 @@
int uid = UserHandle.getUid(user.id, appId);
updateRuleForAppIdleLocked(uid);
updateRuleForDeviceIdleLocked(uid);
+ updateRulesForRestrictPowerLocked(uid);
}
}
}
@@ -2596,6 +2617,12 @@
uidRules = RULE_REJECT_ALL;
}
+ // Check powersave state, which is whitelist
+ if (mFirewallChainStates.get(FIREWALL_CHAIN_POWERSAVE)
+ && mUidFirewallPowerSaveRules.get(uid, FIREWALL_RULE_DEFAULT) != FIREWALL_RULE_ALLOW) {
+ uidRules = RULE_REJECT_ALL;
+ }
+
// Check standby state, which is blacklist
if (mFirewallChainStates.get(FIREWALL_CHAIN_STANDBY)
&& mUidFirewallStandbyRules.get(uid, FIREWALL_RULE_DEFAULT) == FIREWALL_RULE_DENY) {
@@ -2823,6 +2850,8 @@
mUidFirewallDozableRules.put(uid, rule);
} else if (chain == FIREWALL_CHAIN_STANDBY) {
mUidFirewallStandbyRules.put(uid, rule);
+ } else if (chain == FIREWALL_CHAIN_POWERSAVE) {
+ mUidFirewallPowerSaveRules.put(uid, rule);
}
try {
diff --git a/services/core/java/com/android/server/notification/NotificationComparator.java b/services/core/java/com/android/server/notification/NotificationComparator.java
index 5e4703d..7dff2c1 100644
--- a/services/core/java/com/android/server/notification/NotificationComparator.java
+++ b/services/core/java/com/android/server/notification/NotificationComparator.java
@@ -28,10 +28,11 @@
final int leftImportance = left.getImportance();
final int rightImportance = right.getImportance();
if (leftImportance != rightImportance) {
- // by priority, high to low
+ // by importance, high to low
return -1 * Integer.compare(leftImportance, rightImportance);
}
+ // Whether or not the notification can bypass DND.
final int leftPackagePriority = left.getPackagePriority();
final int rightPackagePriority = right.getPackagePriority();
if (leftPackagePriority != rightPackagePriority) {
@@ -39,6 +40,13 @@
return -1 * Integer.compare(leftPackagePriority, rightPackagePriority);
}
+ final int leftPriority = left.sbn.getNotification().priority;
+ final int rightPriority = right.sbn.getNotification().priority;
+ if (leftPriority != rightPriority) {
+ // by priority, high to low
+ return -1 * Integer.compare(leftPriority, rightPriority);
+ }
+
final float leftPeople = left.getContactAffinity();
final float rightPeople = right.getContactAffinity();
if (leftPeople != rightPeople) {
diff --git a/services/core/java/com/android/server/notification/NotificationIntrusivenessExtractor.java b/services/core/java/com/android/server/notification/NotificationIntrusivenessExtractor.java
index b57cc75..bcdeb66 100644
--- a/services/core/java/com/android/server/notification/NotificationIntrusivenessExtractor.java
+++ b/services/core/java/com/android/server/notification/NotificationIntrusivenessExtractor.java
@@ -23,7 +23,7 @@
import android.util.Slog;
/**
- * This {@link com.android.server.notification.NotificationSignalExtractor} noticies noisy
+ * This {@link com.android.server.notification.NotificationSignalExtractor} notices noisy
* notifications and marks them to get a temporary ranking bump.
*/
public class NotificationIntrusivenessExtractor implements NotificationSignalExtractor {
@@ -44,9 +44,15 @@
return null;
}
- final Notification notification = record.getNotification();
- if (record.getImportance() > NotificationListenerService.Ranking.IMPORTANCE_DEFAULT) {
- record.setRecentlyIntrusive(true);
+ if (record.getImportance() >= NotificationListenerService.Ranking.IMPORTANCE_DEFAULT) {
+ final Notification notification = record.getNotification();
+ if ((notification.defaults & Notification.DEFAULT_VIBRATE) != 0 ||
+ notification.vibrate != null ||
+ (notification.defaults & Notification.DEFAULT_SOUND) != 0 ||
+ notification.sound != null ||
+ notification.fullScreenIntent != null) {
+ record.setRecentlyIntrusive(true);
+ }
}
return new RankingReconsideration(record.getKey(), HANG_TIME_MS) {
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index e8d27db..3855579 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -1320,7 +1320,7 @@
@Override
public int getImportance(String pkg, int uid) {
- checkCallerIsSystem();
+ enforceSystemOrSystemUI("Caller not system or systemui");
return mRankingHelper.getImportance(pkg, uid);
}
diff --git a/services/core/java/com/android/server/pm/Installer.java b/services/core/java/com/android/server/pm/Installer.java
index 1476e6e..93dcc72 100644
--- a/services/core/java/com/android/server/pm/Installer.java
+++ b/services/core/java/com/android/server/pm/Installer.java
@@ -203,6 +203,11 @@
mInstaller.execute("linkfile", relativePath, fromBase, toBase);
}
+ public void moveAb(String apkPath, String instructionSet, String outputPath)
+ throws InstallerException {
+ mInstaller.execute("move_ab", apkPath, instructionSet, outputPath);
+ }
+
private static void assertValidInstructionSet(String instructionSet)
throws InstallerException {
for (String abi : Build.SUPPORTED_ABIS) {
diff --git a/services/core/java/com/android/server/pm/OtaDexoptService.java b/services/core/java/com/android/server/pm/OtaDexoptService.java
index 94b3b2d..67aeed1 100644
--- a/services/core/java/com/android/server/pm/OtaDexoptService.java
+++ b/services/core/java/com/android/server/pm/OtaDexoptService.java
@@ -16,36 +16,28 @@
package com.android.server.pm;
-import android.app.AppGlobals;
+import static com.android.server.pm.Installer.DEXOPT_OTA;
+import static com.android.server.pm.InstructionSets.getAppDexInstructionSets;
+import static com.android.server.pm.InstructionSets.getDexCodeInstructionSets;
+
import android.content.Context;
-import android.content.Intent;
import android.content.pm.IOtaDexopt;
import android.content.pm.PackageParser;
import android.content.pm.PackageParser.Package;
-import android.content.pm.ResolveInfo;
import android.os.Environment;
import android.os.RemoteException;
import android.os.ResultReceiver;
import android.os.ServiceManager;
-import android.os.UserHandle;
import android.os.storage.StorageManager;
-import android.util.ArraySet;
import android.util.Log;
+import android.util.Slog;
-import dalvik.system.DexFile;
+import com.android.internal.os.InstallerConnection.InstallerException;
import java.io.File;
import java.io.FileDescriptor;
-import java.util.ArrayList;
import java.util.Collection;
-import java.util.Date;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.LinkedList;
import java.util.List;
-import java.util.Set;
-
-import static com.android.server.pm.Installer.DEXOPT_OTA;
/**
* A service for A/B OTA dexopting.
@@ -70,6 +62,9 @@
// Use the package manager install and install lock here for the OTA dex optimizer.
mPackageDexOptimizer = new OTADexoptPackageDexOptimizer(packageManagerService.mInstaller,
packageManagerService.mInstallLock, context);
+
+ // Now it's time to check whether we need to move any A/B artifacts.
+ moveAbArtifacts(packageManagerService.mInstaller);
}
public static OtaDexoptService main(Context context,
@@ -150,20 +145,50 @@
false /* extractOnly */);
}
- private ArraySet<String> getPackageNamesForIntent(Intent intent, int userId) {
- List<ResolveInfo> ris = null;
- try {
- ris = AppGlobals.getPackageManager().queryIntentReceivers(
- intent, null, 0, userId);
- } catch (RemoteException e) {
+ private void moveAbArtifacts(Installer installer) {
+ if (mDexoptPackages != null) {
+ throw new IllegalStateException("Should not be ota-dexopting when trying to move.");
}
- ArraySet<String> pkgNames = new ArraySet<String>(ris == null ? 0 : ris.size());
- if (ris != null) {
- for (ResolveInfo ri : ris) {
- pkgNames.add(ri.activityInfo.packageName);
+
+ // Look into all packages.
+ Collection<PackageParser.Package> pkgs = mPackageManagerService.getPackages();
+ for (PackageParser.Package pkg : pkgs) {
+ if (pkg == null) {
+ continue;
+ }
+
+ // Does the package have code? If not, there won't be any artifacts.
+ if (!PackageDexOptimizer.canOptimizePackage(pkg)) {
+ continue;
+ }
+ if (pkg.codePath == null) {
+ Slog.w(TAG, "Package " + pkg + " can be optimized but has null codePath");
+ continue;
+ }
+
+ // If the path is in /system or /vendor, ignore. It will have been ota-dexopted into
+ // /data/ota and moved into the dalvik-cache already.
+ if (pkg.codePath.startsWith("/system") || pkg.codePath.startsWith("/vendor")) {
+ continue;
+ }
+
+ final String[] instructionSets = getAppDexInstructionSets(pkg.applicationInfo);
+ final List<String> paths = pkg.getAllCodePathsExcludingResourceOnly();
+ final String[] dexCodeInstructionSets = getDexCodeInstructionSets(instructionSets);
+ for (String dexCodeInstructionSet : dexCodeInstructionSets) {
+ for (String path : paths) {
+ String oatDir = PackageDexOptimizer.getOatDir(new File(pkg.codePath)).
+ getAbsolutePath();
+
+ // TODO: Check first whether there is an artifact, to save the roundtrip time.
+
+ try {
+ installer.moveAb(path, dexCodeInstructionSet, oatDir);
+ } catch (InstallerException e) {
+ }
+ }
}
}
- return pkgNames;
}
private static class OTADexoptPackageDexOptimizer extends
@@ -180,10 +205,5 @@
return dexoptFlags | DEXOPT_OTA;
}
- @Override
- protected void recordSuccessfulDexopt(Package pkg, String instructionSet) {
- // Never record the dexopt, as it's in the B partition.
- }
-
}
}
diff --git a/services/core/java/com/android/server/pm/PackageDexOptimizer.java b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
index a084d86..c9613b4 100644
--- a/services/core/java/com/android/server/pm/PackageDexOptimizer.java
+++ b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
@@ -113,15 +113,6 @@
}
/**
- * Determine whether the package should be skipped for the given instruction set. A return
- * value of true means the package will be skipped. A return value of false means that the
- * package will be further investigated, and potentially compiled.
- */
- protected boolean shouldSkipBasedOnISA(PackageParser.Package pkg, String instructionSet) {
- return pkg.mDexOptPerformed.contains(instructionSet);
- }
-
- /**
* Adjust the given dexopt-needed value. Can be overridden to influence the decision to
* optimize or not (and in what way).
*/
@@ -136,13 +127,6 @@
return dexoptFlags;
}
- /**
- * Update the package status after a successful compilation.
- */
- protected void recordSuccessfulDexopt(PackageParser.Package pkg, String instructionSet) {
- pkg.mDexOptPerformed.add(instructionSet);
- }
-
private int performDexOptLI(PackageParser.Package pkg, String[] targetInstructionSets,
boolean useProfiles, boolean extractOnly) {
final String[] instructionSets = targetInstructionSets != null ?
@@ -159,11 +143,6 @@
boolean performedDexOpt = false;
final String[] dexCodeInstructionSets = getDexCodeInstructionSets(instructionSets);
for (String dexCodeInstructionSet : dexCodeInstructionSets) {
- if (!useProfiles && shouldSkipBasedOnISA(pkg, dexCodeInstructionSet)) {
- // Skip only if we do not use profiles since they might trigger a recompilation.
- continue;
- }
-
for (String path : paths) {
if (useProfiles && isUsedByOtherApps(path)) {
// We cannot use profile guided compilation if the apk was used by another app.
@@ -172,35 +151,44 @@
int dexoptNeeded;
try {
- dexoptNeeded = DexFile.getDexOptNeeded(path, pkg.packageName,
- dexCodeInstructionSet, /* defer */false);
+ int compilationTypeMask = 0;
+ if (extractOnly) {
+ // For extract only, any type of compilation is good.
+ compilationTypeMask = DexFile.COMPILATION_TYPE_FULL
+ | DexFile.COMPILATION_TYPE_PROFILE_GUIDE
+ | DexFile.COMPILATION_TYPE_EXTRACT_ONLY;
+ } else {
+ // Branch taken for profile guide and full compilation.
+ // Profile guide compilation should only recompile a previous
+ // profile compiled/extract only file and should not be attempted if the
+ // apk is already fully compiled. So test against a full compilation type.
+ compilationTypeMask = DexFile.COMPILATION_TYPE_FULL;
+ }
+ dexoptNeeded = DexFile.getDexOptNeeded(path,
+ dexCodeInstructionSet, compilationTypeMask);
} catch (IOException ioe) {
Slog.w(TAG, "IOException reading apk: " + path, ioe);
return DEX_OPT_FAILED;
}
dexoptNeeded = adjustDexoptNeeded(dexoptNeeded);
- if (dexoptNeeded == DexFile.NO_DEXOPT_NEEDED) {
- if (useProfiles) {
- // Profiles may trigger re-compilation. The final decision is taken in
- // installd.
- dexoptNeeded = DexFile.DEX2OAT_NEEDED;
- } else {
- // No dexopt needed and we don't use profiles. Nothing to do.
- continue;
- }
- }
final String dexoptType;
String oatDir = null;
- if (dexoptNeeded == DexFile.DEX2OAT_NEEDED) {
- dexoptType = "dex2oat";
- oatDir = createOatDirIfSupported(pkg, dexCodeInstructionSet);
- } else if (dexoptNeeded == DexFile.PATCHOAT_NEEDED) {
- dexoptType = "patchoat";
- } else if (dexoptNeeded == DexFile.SELF_PATCHOAT_NEEDED) {
- dexoptType = "self patchoat";
- } else {
- throw new IllegalStateException("Invalid dexopt needed: " + dexoptNeeded);
+ switch (dexoptNeeded) {
+ case DexFile.NO_DEXOPT_NEEDED:
+ continue;
+ case DexFile.DEX2OAT_NEEDED:
+ dexoptType = "dex2oat";
+ oatDir = createOatDirIfSupported(pkg, dexCodeInstructionSet);
+ break;
+ case DexFile.PATCHOAT_NEEDED:
+ dexoptType = "patchoat";
+ break;
+ case DexFile.SELF_PATCHOAT_NEEDED:
+ dexoptType = "self patchoat";
+ break;
+ default:
+ throw new IllegalStateException("Invalid dexopt:" + dexoptNeeded);
}
@@ -226,15 +214,6 @@
Slog.w(TAG, "Failed to dexopt", e);
}
}
-
- if (!extractOnly) {
- // At this point we haven't failed dexopt and we haven't deferred dexopt. We must
- // either have either succeeded dexopt, or have had getDexOptNeeded tell us
- // it isn't required. We therefore mark that this package doesn't need dexopt unless
- // it's forced. performedDexOpt will tell us whether we performed dex-opt or skipped
- // it.
- recordSuccessfulDexopt(pkg, dexCodeInstructionSet);
- }
}
// If we've gotten here, we're sure that no error occurred and that we haven't
@@ -317,12 +296,6 @@
}
@Override
- protected boolean shouldSkipBasedOnISA(Package pkg, String instructionSet) {
- // Forced compilation, never skip.
- return false;
- }
-
- @Override
protected int adjustDexoptNeeded(int dexoptNeeded) {
// Ensure compilation, no matter the current state.
// TODO: The return value is wrong when patchoat is needed.
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 7f49765..5562e76 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -62,7 +62,9 @@
import static android.content.pm.PackageManager.MATCH_ALL;
import static android.content.pm.PackageManager.MATCH_DEBUG_TRIAGED_MISSING;
import static android.content.pm.PackageManager.MATCH_DISABLED_COMPONENTS;
+import static android.content.pm.PackageManager.MATCH_ENCRYPTION_AWARE;
import static android.content.pm.PackageManager.MATCH_ENCRYPTION_AWARE_AND_UNAWARE;
+import static android.content.pm.PackageManager.MATCH_ENCRYPTION_UNAWARE;
import static android.content.pm.PackageManager.MATCH_SYSTEM_ONLY;
import static android.content.pm.PackageManager.MATCH_UNINSTALLED_PACKAGES;
import static android.content.pm.PackageManager.MOVE_FAILED_DEVICE_ADMIN;
@@ -358,6 +360,7 @@
static final int SCAN_MOVE = 1<<13;
static final int SCAN_INITIAL = 1<<14;
static final int SCAN_CHECK_ONLY = 1<<15;
+ static final int SCAN_DONT_KILL_APP = 1<<17;
static final int REMOVE_CHATTY = 1<<16;
@@ -497,6 +500,9 @@
final ArrayMap<String, PackageParser.Package> mPackages =
new ArrayMap<String, PackageParser.Package>();
+ final ArrayMap<String, Set<String>> mKnownCodebase =
+ new ArrayMap<String, Set<String>>();
+
// Tracks available target package names -> overlay package paths.
final ArrayMap<String, ArrayMap<String, PackageParser.Package>> mOverlays =
new ArrayMap<String, ArrayMap<String, PackageParser.Package>>();
@@ -637,9 +643,6 @@
// List of packages names to keep cached, even if they are uninstalled for all users
private List<String> mKeepUninstalledPackages;
- private boolean mUseJitProfiles =
- SystemProperties.getBoolean("dalvik.vm.usejitprofiles", false);
-
private static class IFVerificationParams {
PackageParser.Package pkg;
boolean replacing;
@@ -1426,19 +1429,21 @@
final boolean grantPermissions = (args.installFlags
& PackageManager.INSTALL_GRANT_RUNTIME_PERMISSIONS) != 0;
+ final boolean killApp = (args.installFlags
+ & PackageManager.INSTALL_DONT_KILL_APP) == 0;
final String[] grantedPermissions = args.installGrantPermissions;
// Handle the parent package
- handlePackagePostInstall(parentRes, grantPermissions, grantedPermissions,
- args.observer);
+ handlePackagePostInstall(parentRes, grantPermissions, killApp,
+ grantedPermissions, args.observer);
// Handle the child packages
final int childCount = (parentRes.addedChildPackages != null)
? parentRes.addedChildPackages.size() : 0;
for (int i = 0; i < childCount; i++) {
PackageInstalledInfo childRes = parentRes.addedChildPackages.valueAt(i);
- handlePackagePostInstall(childRes, grantPermissions, grantedPermissions,
- args.observer);
+ handlePackagePostInstall(childRes, grantPermissions, killApp,
+ grantedPermissions, args.observer);
}
// Log tracing if needed
@@ -1633,11 +1638,12 @@
}
private void handlePackagePostInstall(PackageInstalledInfo res, boolean grantPermissions,
- String[] grantedPermissions, IPackageInstallObserver2 installObserver) {
+ boolean killApp, String[] grantedPermissions,
+ IPackageInstallObserver2 installObserver) {
if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
// Send the removed broadcasts
if (res.removedInfo != null) {
- res.removedInfo.sendPackageRemovedBroadcasts();
+ res.removedInfo.sendPackageRemovedBroadcasts(killApp);
}
// Now that we successfully installed the package, grant runtime
@@ -2159,10 +2165,12 @@
}
try {
- int dexoptNeeded = DexFile.getDexOptNeeded(lib, null, dexCodeInstructionSet, false);
+ // Shared libraries do not have profiles so we perform a full
+ // AOT compilation (if needed).
+ int dexoptNeeded = DexFile.getDexOptNeeded(
+ lib, dexCodeInstructionSet,
+ DexFile.COMPILATION_TYPE_FULL);
if (dexoptNeeded != DexFile.NO_DEXOPT_NEEDED) {
- // Shared libraries do not have profiles so we perform a full
- // AOT compilation.
mInstaller.dexopt(lib, Process.SYSTEM_UID, dexCodeInstructionSet,
dexoptNeeded, DEXOPT_PUBLIC /*dexFlags*/,
StorageManager.UUID_PRIVATE_INTERNAL,
@@ -4232,7 +4240,8 @@
// TODO: remove these terrible hacks
if (actionName.startsWith("android.net.netmon.lingerExpired")
|| actionName.startsWith("com.android.server.sip.SipWakeupTimer")
- || actionName.startsWith("com.android.internal.telephony.data-reconnect")) {
+ || actionName.startsWith("com.android.internal.telephony.data-reconnect")
+ || actionName.startsWith("android.net.netmon.launchCaptivePortalApp")) {
return true;
}
}
@@ -6072,9 +6081,16 @@
final int userId = UserHandle.getCallingUserId();
while (i.hasNext()) {
final PackageParser.Package p = i.next();
- if (p.applicationInfo != null
- && (p.applicationInfo.flags&ApplicationInfo.FLAG_PERSISTENT) != 0
- && (!mSafeMode || isSystemApp(p))) {
+ if (p.applicationInfo == null) continue;
+
+ final boolean matchesUnaware = ((flags & MATCH_ENCRYPTION_UNAWARE) != 0)
+ && !p.applicationInfo.isEncryptionAware();
+ final boolean matchesAware = ((flags & MATCH_ENCRYPTION_AWARE) != 0)
+ && p.applicationInfo.isEncryptionAware();
+
+ if ((p.applicationInfo.flags & ApplicationInfo.FLAG_PERSISTENT) != 0
+ && (!mSafeMode || isSystemApp(p))
+ && (matchesUnaware || matchesAware)) {
PackageSetting ps = mSettings.mPackages.get(p.packageName);
if (ps != null) {
ApplicationInfo ai = PackageParser.generateApplicationInfo(p, flags,
@@ -6828,7 +6844,7 @@
// Extract pacakges only if profile-guided compilation is enabled because
// otherwise BackgroundDexOptService will not dexopt them later.
- if (!mUseJitProfiles || !isUpgrade()) {
+ if (!isUpgrade()) {
return;
}
@@ -6910,10 +6926,6 @@
targetInstructionSet = instructionSet != null ? instructionSet :
getPrimaryInstructionSet(p.applicationInfo);
- if (!force && !useProfiles && p.mDexOptPerformed.contains(targetInstructionSet)) {
- // Skip only if we do not use profiles since they might trigger a recompilation.
- return false;
- }
}
long callingId = Binder.clearCallingIdentity();
try {
@@ -7894,13 +7906,17 @@
// Request the ActivityManager to kill the process(only for existing packages)
// so that we do not end up in a confused state while the user is still using the older
// version of the application while the new one gets installed.
- if ((scanFlags & SCAN_REPLACING) != 0) {
- Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "killApplication");
+ final boolean isReplacing = (scanFlags & SCAN_REPLACING) != 0;
+ final boolean killApp = (scanFlags & SCAN_DONT_KILL_APP) == 0;
+ if (killApp) {
+ if (isReplacing) {
+ Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "killApplication");
- killApplication(pkg.applicationInfo.packageName,
- pkg.applicationInfo.uid, "replace pkg");
+ killApplication(pkg.applicationInfo.packageName,
+ pkg.applicationInfo.uid, "replace pkg");
- Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
+ Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
+ }
}
// Also need to kill any apps that are dependent on the library.
@@ -10589,7 +10605,7 @@
info.removedPackage = packageName;
info.removedUsers = new int[] {userId};
info.uid = UserHandle.getUid(userId, pkgSetting.appId);
- info.sendPackageRemovedBroadcasts();
+ info.sendPackageRemovedBroadcasts(true /*killApp*/);
}
private void sendPackagesSuspendedForUser(String[] pkgList, int userId, boolean suspended) {
@@ -13072,6 +13088,15 @@
}
}
+ public List<String> getPreviousCodePaths(String packageName) {
+ final PackageSetting ps = mSettings.mPackages.get(packageName);
+ final List<String> result = new ArrayList<String>();
+ if (ps != null && ps.oldCodePaths != null) {
+ result.addAll(ps.oldCodePaths);
+ }
+ return result;
+ }
+
private void replaceNonSystemPackageLI(PackageParser.Package deletedPackage,
PackageParser.Package pkg, int parseFlags, int scanFlags, UserHandle user,
int[] allUsers, String installerPackageName, PackageInstalledInfo res) {
@@ -13081,12 +13106,16 @@
String pkgName = deletedPackage.packageName;
boolean deletedPkg = true;
boolean addedPkg = false;
+ boolean updatedSettings = false;
+ final boolean killApp = (scanFlags & SCAN_DONT_KILL_APP) == 0;
+ final int deleteFlags = PackageManager.DELETE_KEEP_DATA
+ | (killApp ? 0 : PackageManager.DELETE_DONT_KILL_APP);
final long origUpdateTime = (pkg.mExtras != null)
? ((PackageSetting)pkg.mExtras).lastUpdateTime : 0;
// First delete the existing package while retaining the data directory
- if (!deletePackageLI(pkgName, null, true, allUsers, PackageManager.DELETE_KEEP_DATA,
+ if (!deletePackageLI(pkgName, null, true, allUsers, deleteFlags,
res.removedInfo, true, pkg)) {
// If the existing package wasn't successfully deleted
res.setError(INSTALL_FAILED_REPLACE_COULDNT_DELETE, "replaceNonSystemPackageLI");
@@ -13112,6 +13141,27 @@
final PackageParser.Package newPackage = scanPackageTracedLI(pkg, parseFlags,
scanFlags | SCAN_UPDATE_TIME, System.currentTimeMillis(), user);
updateSettingsLI(newPackage, installerPackageName, allUsers, res, user);
+
+ // Update the in-memory copy of the previous code paths.
+ PackageSetting ps = mSettings.mPackages.get(pkgName);
+ if (!killApp) {
+ if (ps.oldCodePaths == null) {
+ ps.oldCodePaths = new ArraySet<>();
+ }
+ Collections.addAll(ps.oldCodePaths, deletedPackage.baseCodePath);
+ if (deletedPackage.splitCodePaths != null) {
+ Collections.addAll(ps.oldCodePaths, deletedPackage.splitCodePaths);
+ }
+ } else {
+ ps.oldCodePaths = null;
+ }
+ if (ps.childPackageNames != null) {
+ for (int i = ps.childPackageNames.size() - 1; i >= 0; --i) {
+ final String childPkgName = ps.childPackageNames.get(i);
+ final PackageSetting childPs = mSettings.mPackages.get(childPkgName);
+ childPs.oldCodePaths = ps.oldCodePaths;
+ }
+ }
prepareAppDataAfterInstall(newPackage);
addedPkg = true;
} catch (PackageManagerException e) {
@@ -13124,7 +13174,7 @@
// Revert all internal state mutations and added folders for the failed install
if (addedPkg) {
- deletePackageLI(pkgName, null, true, allUsers, PackageManager.DELETE_KEEP_DATA,
+ deletePackageLI(pkgName, null, true, allUsers, deleteFlags,
res.removedInfo, true, null);
}
@@ -13577,6 +13627,9 @@
// moving a complete application; perform an initial scan on the new install location
scanFlags |= SCAN_INITIAL;
}
+ if ((installFlags & PackageManager.INSTALL_DONT_KILL_APP) != 0) {
+ scanFlags |= SCAN_DONT_KILL_APP;
+ }
// Result object to be returned
res.setReturnCode(PackageManager.INSTALL_SUCCEEDED);
@@ -13843,21 +13896,17 @@
return;
}
- // Extract package to save the VM unzipping the APK in memory during
- // launch. Only do this if profile-guided compilation is enabled because
- // otherwise BackgroundDexOptService will not dexopt the package later.
- if (mUseJitProfiles) {
- Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "dexopt");
- // Do not run PackageDexOptimizer through the local performDexOpt
- // method because `pkg` is not in `mPackages` yet.
- int result = mPackageDexOptimizer.performDexOpt(pkg, null /* instructionSets */,
- false /* useProfiles */, true /* extractOnly */);
- Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
- if (result == PackageDexOptimizer.DEX_OPT_FAILED) {
- String msg = "Extracking package failed for " + pkgName;
- res.setError(INSTALL_FAILED_DEXOPT, msg);
- return;
- }
+
+ Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "dexopt");
+ // Do not run PackageDexOptimizer through the local performDexOpt
+ // method because `pkg` is not in `mPackages` yet.
+ int result = mPackageDexOptimizer.performDexOpt(pkg, null /* instructionSets */,
+ false /* useProfiles */, true /* extractOnly */);
+ Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
+ if (result == PackageDexOptimizer.DEX_OPT_FAILED) {
+ String msg = "Extracking package failed for " + pkgName;
+ res.setError(INSTALL_FAILED_DEXOPT, msg);
+ return;
}
}
@@ -14301,7 +14350,8 @@
}
if (res) {
- info.sendPackageRemovedBroadcasts();
+ final boolean killApp = (flags & PackageManager.INSTALL_DONT_KILL_APP) == 0;
+ info.sendPackageRemovedBroadcasts(killApp);
info.sendSystemPackageUpdatedBroadcasts();
info.sendSystemPackageAppearedBroadcasts();
}
@@ -14333,12 +14383,12 @@
ArrayMap<String, PackageRemovedInfo> removedChildPackages;
ArrayMap<String, PackageInstalledInfo> appearedChildPackages;
- void sendPackageRemovedBroadcasts() {
- sendPackageRemovedBroadcastInternal();
+ void sendPackageRemovedBroadcasts(boolean killApp) {
+ sendPackageRemovedBroadcastInternal(killApp);
final int childCount = removedChildPackages != null ? removedChildPackages.size() : 0;
for (int i = 0; i < childCount; i++) {
PackageRemovedInfo childInfo = removedChildPackages.valueAt(i);
- childInfo.sendPackageRemovedBroadcastInternal();
+ childInfo.sendPackageRemovedBroadcastInternal(killApp);
}
}
@@ -14380,10 +14430,11 @@
null, 0, removedPackage, null, null);
}
- private void sendPackageRemovedBroadcastInternal() {
+ private void sendPackageRemovedBroadcastInternal(boolean killApp) {
Bundle extras = new Bundle(2);
extras.putInt(Intent.EXTRA_UID, removedAppId >= 0 ? removedAppId : uid);
extras.putBoolean(Intent.EXTRA_DATA_REMOVED, dataRemoved);
+ extras.putBoolean(Intent.EXTRA_DONT_KILL_APP, !killApp);
if (isUpdate || isRemovedPackageSystemUpdate) {
extras.putBoolean(Intent.EXTRA_REPLACING, true);
}
@@ -14874,7 +14925,10 @@
} else {
if (DEBUG_REMOVE) Slog.d(TAG, "Removing non-system package: " + ps.name);
// Kill application pre-emptively especially for apps on sd.
- killApplication(packageName, ps.appId, "uninstall pkg");
+ final boolean killApp = (flags & PackageManager.DELETE_DONT_KILL_APP) == 0;
+ if (killApp) {
+ killApplication(packageName, ps.appId, "uninstall pkg");
+ }
ret = deleteInstalledPackageLI(ps, deleteCodeAndResources, flags, allUserHandles,
outInfo, writeSettings, replacingPackage);
}
@@ -19123,6 +19177,11 @@
return permissionsState.isPermissionReviewRequired(userId);
}
}
+
+ @Override
+ public ApplicationInfo getApplicationInfo(String packageName, int userId) {
+ return PackageManagerService.this.getApplicationInfo(packageName, 0 /*flags*/, userId);
+ }
}
@Override
@@ -19150,4 +19209,14 @@
boolean isHistoricalPackageUsageAvailable() {
return mPackageUsage.isHistoricalPackageUsageAvailable();
}
+
+ /**
+ * Return a <b>copy</b> of the collection of packages known to the package manager.
+ * @return A copy of the values of mPackages.
+ */
+ Collection<PackageParser.Package> getPackages() {
+ synchronized (mPackages) {
+ return new ArrayList<>(mPackages.values());
+ }
+ }
}
diff --git a/services/core/java/com/android/server/pm/PackageSettingBase.java b/services/core/java/com/android/server/pm/PackageSettingBase.java
index e5eec7e..1434718 100644
--- a/services/core/java/com/android/server/pm/PackageSettingBase.java
+++ b/services/core/java/com/android/server/pm/PackageSettingBase.java
@@ -30,6 +30,7 @@
import java.io.File;
import java.util.ArrayList;
import java.util.List;
+import java.util.Set;
/**
* Settings base class for pending and resolved classes.
@@ -118,7 +119,14 @@
* platform will refuse to launch packages in a frozen state.
*/
boolean frozen = false;
-
+ /**
+ * Non-persisted value. During an "upgrade without restart", we need the set
+ * of all previous code paths so we can surgically add the new APKs to the
+ * active classloader. If at any point an application is upgraded with a
+ * restart, this field will be cleared since the classloader would be created
+ * using the full set of code paths when the package's process is started.
+ */
+ Set<String> oldCodePaths;
PackageSettingBase origPackage;
/** Package name of the app that installed this package */
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 1652185..310ad53 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -3049,7 +3049,7 @@
tmpPa.dump(new LogPrinter(Log.DEBUG, TAG), " ");
}
Intent intent = new Intent();
- int flags = 0;
+ int flags = PackageManager.MATCH_ENCRYPTION_AWARE_AND_UNAWARE;
intent.setAction(tmpPa.getAction(0));
for (int i=0; i<tmpPa.countCategories(); i++) {
String cat = tmpPa.getCategory(i);
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index f901f95..6218c4e 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -60,6 +60,7 @@
import com.android.internal.app.IAppOpsService;
import com.android.internal.app.IBatteryStats;
import com.android.internal.os.BackgroundThread;
+import com.android.internal.util.ArrayUtils;
import com.android.server.EventLogTags;
import com.android.server.ServiceThread;
import com.android.server.SystemService;
@@ -254,6 +255,9 @@
// True if boot completed occurred. We keep the screen on until this happens.
private boolean mBootCompleted;
+ // Runnables that should be triggered on boot completed
+ private Runnable[] mBootCompletedRunnables;
+
// True if auto-suspend mode is enabled.
// Refer to autosuspend.h.
private boolean mHalAutoSuspendModeEnabled;
@@ -525,6 +529,14 @@
userActivityNoUpdateLocked(
now, PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, Process.SYSTEM_UID);
updatePowerStateLocked();
+
+ if (!ArrayUtils.isEmpty(mBootCompletedRunnables)) {
+ Slog.d(TAG, "Posting " + mBootCompletedRunnables.length + " delayed runnables");
+ for (Runnable r : mBootCompletedRunnables) {
+ BackgroundThread.getHandler().post(r);
+ }
+ }
+ mBootCompletedRunnables = null;
}
}
}
@@ -750,6 +762,16 @@
mDirty |= DIRTY_SETTINGS;
}
+ private void postAfterBootCompleted(Runnable r) {
+ if (mBootCompleted) {
+ BackgroundThread.getHandler().post(r);
+ } else {
+ Slog.d(TAG, "Delaying runnable until system is booted");
+ mBootCompletedRunnables = ArrayUtils.appendElement(Runnable.class,
+ mBootCompletedRunnables, r);
+ }
+ }
+
void updateLowPowerModeLocked() {
if (mIsPowered && mLowPowerModeSetting) {
if (DEBUG_SPEW) {
@@ -767,7 +789,7 @@
if (mLowPowerModeEnabled != lowPowerModeEnabled) {
mLowPowerModeEnabled = lowPowerModeEnabled;
powerHintInternal(POWER_HINT_LOW_POWER, lowPowerModeEnabled ? 1 : 0);
- BackgroundThread.getHandler().post(new Runnable() {
+ postAfterBootCompleted(new Runnable() {
@Override
public void run() {
Intent intent = new Intent(PowerManager.ACTION_POWER_SAVE_MODE_CHANGING)
diff --git a/services/core/java/com/android/server/vr/VrManagerService.java b/services/core/java/com/android/server/vr/VrManagerService.java
index 2f076d1..7611527 100644
--- a/services/core/java/com/android/server/vr/VrManagerService.java
+++ b/services/core/java/com/android/server/vr/VrManagerService.java
@@ -15,9 +15,12 @@
*/
package com.android.server.vr;
+import android.app.AppOpsManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
+import android.os.Binder;
+import android.os.IBinder;
import android.os.UserHandle;
import android.util.ArraySet;
import android.util.Slog;
@@ -40,6 +43,9 @@
private static native void setVrModeNative(boolean enabled);
private final Object mLock = new Object();
+
+ private final IBinder mOverlayToken = new Binder();
+
private boolean mVrModeEnabled = false;
private ArraySet<VrStateListener> mListeners = new ArraySet<>();
@@ -97,11 +103,25 @@
// Log mode change event.
Slog.i(TAG, "VR mode " + ((mVrModeEnabled) ? "enabled" : "disabled"));
setVrModeNative(mVrModeEnabled);
+ updateOverlayStateLocked();
onVrModeChangedLocked();
}
}
}
+ private void updateOverlayStateLocked() {
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ AppOpsManager appOpsManager = getContext().getSystemService(AppOpsManager.class);
+ if (appOpsManager != null) {
+ appOpsManager.setUserRestriction(AppOpsManager.OP_SYSTEM_ALERT_WINDOW,
+ mVrModeEnabled, mOverlayToken);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
private boolean getVrMode() {
synchronized (mLock) {
return mVrModeEnabled;
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
index ba0d340..a0a971a 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
@@ -882,6 +882,9 @@
wallpaper = mLockWallpaperMap.get(userId);
if (wallpaper == null) {
// It's already gone; we're done.
+ if (DEBUG) {
+ Slog.i(TAG, "Lock wallpaper already cleared");
+ }
return;
}
} else {
@@ -902,14 +905,19 @@
wallpaper.wallpaperFile.delete();
wallpaper.cropFile.delete();
if (which == FLAG_SET_LOCK) {
+ mLockWallpaperMap.remove(userId);
final IWallpaperManagerCallback cb = mKeyguardListener;
if (cb != null) {
+ if (DEBUG) {
+ Slog.i(TAG, "Notifying keyguard of lock wallpaper clear");
+ }
try {
cb.onWallpaperChanged();
} catch (RemoteException e) {
// Oh well it went away; no big deal
}
}
+ saveSettingsLocked(userId);
return;
}
}
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index f9e258d..ecfbc0a 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -375,6 +375,7 @@
// The application has stopped, so destroy any surfaces which were keeping alive
// in case they were still being used.
void notifyAppStopped() {
+ if (DEBUG_ADD_REMOVE) Slog.v(TAG, "notifyAppStopped: " + this);
mAppStopped = true;
destroySurfaces();
@@ -472,7 +473,7 @@
winNdx = Math.min(winNdx - 1, allAppWindows.size() - 1)) {
WindowState win = allAppWindows.get(winNdx);
if (win.mAppDied) {
- if (DEBUG_WINDOW_MOVEMENT) {
+ if (DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) {
Slog.w(TAG, "removeAllDeadWindows: " + win);
}
// Set mDestroying, we don't want any animation or delayed removal here.
diff --git a/services/core/java/com/android/server/wm/BoundsAnimationController.java b/services/core/java/com/android/server/wm/BoundsAnimationController.java
index f0efebe..79d3d84 100644
--- a/services/core/java/com/android/server/wm/BoundsAnimationController.java
+++ b/services/core/java/com/android/server/wm/BoundsAnimationController.java
@@ -54,7 +54,8 @@
private final AnimateBoundsUser mTarget;
private final Rect mFrom;
private final Rect mTo;
- private final Rect mTmpRect;
+ private final Rect mTmpRect = new Rect();
+ private final Rect mTmpTaskBounds = new Rect();
private final boolean mMoveToFullScreen;
// True if this this animation was cancelled and will be replaced the another animation from
// the same {@link #AnimateBoundsUser} target.
@@ -63,17 +64,40 @@
// {@link #AnimateBoundsUser} target.
private final boolean mReplacement;
+ // Depending on whether we are animating from
+ // a smaller to a larger size
+ private final int mFrozenTaskWidth;
+ private final int mFrozenTaskHeight;
+
BoundsAnimator(AnimateBoundsUser target, Rect from, Rect to,
boolean moveToFullScreen, boolean replacement) {
super();
mTarget = target;
mFrom = from;
mTo = to;
- mTmpRect = new Rect();
mMoveToFullScreen = moveToFullScreen;
mReplacement = replacement;
addUpdateListener(this);
addListener(this);
+
+ // If we are animating from smaller to larger, we want to change the task bounds
+ // to their final size immediately so we can use scaling to make the window
+ // larger. Likewise if we are going from bigger to smaller, we want to wait until
+ // the end so we don't have to upscale from the smaller finished size.
+ if (animatingToLargerSize()) {
+ mFrozenTaskWidth = mTo.width();
+ mFrozenTaskHeight = mTo.height();
+ } else {
+ mFrozenTaskWidth = mFrom.width();
+ mFrozenTaskHeight = mFrom.height();
+ }
+ }
+
+ boolean animatingToLargerSize() {
+ if (mFrom.width() * mFrom.height() > mTo.width() * mTo.height()) {
+ return false;
+ }
+ return true;
}
@Override
@@ -87,7 +111,13 @@
if (DEBUG) Slog.d(TAG, "animateUpdate: mTarget=" + mTarget + " mBounds="
+ mTmpRect + " from=" + mFrom + " mTo=" + mTo + " value=" + value
+ " remains=" + remains);
- if (!mTarget.setSize(mTmpRect)) {
+
+ if (remains != 0) {
+ mTmpTaskBounds.set(mTmpRect.left, mTmpRect.top,
+ mTmpRect.left + mFrozenTaskWidth, mTmpRect.top + mFrozenTaskHeight);
+ }
+
+ if (!mTarget.setPinnedStackSize(mTmpRect, remains != 0 ? mTmpTaskBounds : null)) {
// Whoops, the target doesn't feel like animating anymore. Let's immediately finish
// any further animation.
animation.cancel();
@@ -99,6 +129,10 @@
public void onAnimationStart(Animator animation) {
if (DEBUG) Slog.d(TAG, "onAnimationStart: mTarget=" + mTarget
+ " mReplacement=" + mReplacement);
+ if (animatingToLargerSize()) {
+ mTarget.setPinnedStackSize(mFrom, mTo);
+ }
+
if (!mReplacement) {
mTarget.onAnimationStart();
}
@@ -108,6 +142,7 @@
public void onAnimationEnd(Animator animation) {
if (DEBUG) Slog.d(TAG, "onAnimationEnd: mTarget=" + mTarget
+ " mMoveToFullScreen=" + mMoveToFullScreen + " mWillReplace=" + mWillReplace);
+
finishAnimation();
if (mMoveToFullScreen && !mWillReplace) {
mTarget.moveToFullscreen();
@@ -159,6 +194,12 @@
* from the hierarchy and is not valid anymore.
*/
boolean setSize(Rect bounds);
+ /**
+ * Behaves as setSize, but freezes the bounds of any tasks in the target at taskBounds,
+ * to allow for more flexibility during resizing. Only
+ * works for the pinned stack at the moment.
+ */
+ boolean setPinnedStackSize(Rect bounds, Rect taskBounds);
void onAnimationStart();
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index c7b5599..f097eb2 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -19,6 +19,7 @@
import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
+import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
import static android.app.ActivityManager.StackId.HOME_STACK_ID;
import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZEABLE;
import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
@@ -685,6 +686,10 @@
&& mStack != null && StackId.isTaskResizeableByDockedStack(mStack.mStackId);
}
+ boolean isFloating() {
+ return StackId.tasksAreFloating(mStack.mStackId);
+ }
+
/**
* Whether the task should be treated as if it's docked. Returns true if the task
* is currently in docked workspace, or it's side-by-side to a docked task.
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index 07a6514..86327f7 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -111,6 +111,17 @@
private float mMinimizeAmount;
private final int mDockedStackMinimizeThickness;
+ // If this is true, the task will be down or upscaled
+ // to perfectly fit the region it would have been cropped
+ // to.
+ private boolean mForceScaleToCrop = false;
+ // By default, movement animations are applied to all
+ // window movement. If this is true, animations will not
+ // be applied within this stack. This is useful for example
+ // if the windows are moving as the result of a stack animation,
+ // in which case a second window animation would cause jitter.
+ private boolean mFreezeMovementAnimations = false;
+
TaskStack(WindowManagerService service, int stackId) {
mService = service;
mStackId = stackId;
@@ -1128,17 +1139,38 @@
return true;
}
+ public boolean setPinnedStackSize(Rect bounds, Rect tempTaskBounds) {
+ synchronized (mService.mWindowMap) {
+ if (mDisplayContent == null) {
+ return false;
+ }
+ if (mStackId != PINNED_STACK_ID) {
+ Slog.w(TAG_WM, "Attempt to use pinned stack resize animation helper on"
+ + "non pinned stack");
+ return false;
+ }
+ }
+ try {
+ mService.mActivityManager.resizePinnedStack(bounds, tempTaskBounds);
+ } catch (RemoteException e) {
+ // I don't believe you.
+ }
+ return true;
+ }
+
@Override // AnimatesBounds
public void onAnimationStart() {
synchronized (mService.mWindowMap) {
- setDragResizingLocked(true);
+ mFreezeMovementAnimations = true;
+ mForceScaleToCrop = true;
}
}
@Override // AnimatesBounds
public void onAnimationEnd() {
synchronized (mService.mWindowMap) {
- setDragResizingLocked(false);
+ mFreezeMovementAnimations = false;
+ mForceScaleToCrop = false;
mService.requestTraversal();
}
if (mStackId == PINNED_STACK_ID) {
@@ -1163,4 +1195,12 @@
public void getFullScreenBounds(Rect bounds) {
getDisplayContent().getContentRect(bounds);
}
+
+ public boolean getFreezeMovementAnimations() {
+ return mFreezeMovementAnimations;
+ }
+
+ public boolean getForceScaleToCrop() {
+ return mForceScaleToCrop;
+ }
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerDebugConfig.java b/services/core/java/com/android/server/wm/WindowManagerDebugConfig.java
index 0979cd3..ccba88d 100644
--- a/services/core/java/com/android/server/wm/WindowManagerDebugConfig.java
+++ b/services/core/java/com/android/server/wm/WindowManagerDebugConfig.java
@@ -35,7 +35,7 @@
static final boolean DEBUG_RESIZE = false;
static final boolean DEBUG = false;
- static final boolean DEBUG_ADD_REMOVE = false;
+ static final boolean DEBUG_ADD_REMOVE = true;
static final boolean DEBUG_FOCUS = false;
static final boolean DEBUG_FOCUS_LIGHT = DEBUG_FOCUS || false;
static final boolean DEBUG_ANIM = false;
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index fe215d5..7c2a8e3 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -2147,12 +2147,15 @@
void removeWindowLocked(WindowState win) {
win.mWindowRemovalAllowed = true;
+ if (DEBUG_ADD_REMOVE) Slog.v(TAG,
+ "removeWindowLocked: " + win + " callers=" + Debug.getCallers(4));
+
final boolean startingWindow = win.mAttrs.type == TYPE_APPLICATION_STARTING;
if (startingWindow) {
if (DEBUG_STARTING_WINDOW) Slog.d(TAG_WM, "Starting window removed " + win);
}
- if (localLOGV || DEBUG_FOCUS || DEBUG_FOCUS_LIGHT && win==mCurrentFocus) Slog.v(
+ if (localLOGV || DEBUG_FOCUS || DEBUG_FOCUS_LIGHT && win == mCurrentFocus) Slog.v(
TAG_WM, "Remove " + win + " client="
+ Integer.toHexString(System.identityHashCode(win.mClient.asBinder()))
+ ", surfaceController=" + win.mWinAnimator.mSurfaceController + " Callers="
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 40b6b50..4ad021e 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -184,6 +184,10 @@
private Configuration mConfiguration = Configuration.EMPTY;
private Configuration mOverrideConfig = Configuration.EMPTY;
+ // Represents the changes from our override configuration applied
+ // to the global configuration. This is the only form of configuration
+ // which is suitable for delivery to the client.
+ private Configuration mMergedConfiguration = new Configuration();
// Sticky answer to isConfigChanged(), remains true until new Configuration is assigned.
// Used only on {@link #TYPE_KEYGUARD}.
private boolean mConfigHasChanged;
@@ -434,9 +438,9 @@
// If not null, the window that will be used to replace the old one. This is being set when
// the window is added and unset when this window reports its first draw.
WindowState mReplacingWindow = null;
-
// Whether this window is being moved via the resize API
boolean mMovedByResize;
+
/**
* Wake lock for drawing.
* Even though it's slightly more expensive to do so, we will use a separate wake lock
@@ -635,7 +639,7 @@
final Task task = getTask();
final boolean fullscreenTask = task == null || task.isFullscreen();
- final boolean freeformWorkspace = task != null && task.inFreeformWorkspace();
+ final boolean windowsAreFloating = task != null && task.isFloating();
if (fullscreenTask || (isChildWindow()
&& (mAttrs.privateFlags & PRIVATE_FLAG_LAYOUT_CHILD_WINDOW_IN_PARENT_FRAME) != 0)) {
@@ -661,10 +665,10 @@
mContainingFrame.top -= mContainingFrame.bottom - cf.bottom;
}
- if (freeformWorkspace) {
- // In free form mode we have only to set the rectangle if it wasn't set already. No
- // need to intersect it with the (visible) "content frame" since it is allowed to
- // be outside the visible desktop.
+ if (windowsAreFloating) {
+ // In floating modes (e.g. freeform, pinned) we have only to set the rectangle
+ // if it wasn't set already. No need to intersect it with the (visible)
+ // "content frame" since it is allowed to be outside the visible desktop.
if (mContainingFrame.isEmpty()) {
mContainingFrame.set(cf);
}
@@ -720,7 +724,7 @@
// Make sure the content and visible frames are inside of the
// final window frame.
- if (freeformWorkspace && !mFrame.isEmpty()) {
+ if (windowsAreFloating && !mFrame.isEmpty()) {
// Keep the frame out of the blocked system area, limit it in size to the content area
// and make sure that there is always a minimum visible so that the user can drag it
// into a usable area..
@@ -772,9 +776,9 @@
Math.min(mStableFrame.bottom, frame.bottom));
}
- if (!inFreeformWorkspace()) {
- // Freeform windows can be positioned outside of the display frame, but that is not a
- // reason to provide them with overscan insets.
+ if (!windowsAreFloating) {
+ // Windows from floating tasks (e.g. freeform, pinned) may be positioned outside
+ // of the display frame, but that is not a reason to provide them with overscan insets.
mOverscanInsets.set(Math.max(mOverscanFrame.left - frame.left, 0),
Math.max(mOverscanFrame.top - frame.top, 0),
Math.max(frame.right - mOverscanFrame.right, 0),
@@ -1355,6 +1359,11 @@
mConfiguration = newConfig;
mOverrideConfig = newOverrideConfig;
mConfigHasChanged = false;
+
+ mMergedConfiguration.setTo(newConfig);
+ if (newOverrideConfig != null && newOverrideConfig != Configuration.EMPTY) {
+ mMergedConfiguration.updateFrom(newOverrideConfig);
+ }
}
void setHasSurface(boolean hasSurface) {
@@ -1616,9 +1625,10 @@
mTurnOnScreen = true;
}
if (isConfigChanged()) {
+ final Configuration newConfig = updateConfiguration();
if (DEBUG_CONFIGURATION) Slog.i(TAG, "Window " + this + " visible with new config: "
- + mService.mCurConfiguration);
- outConfig.setTo(mService.mCurConfiguration);
+ + newConfig);
+ outConfig.setTo(newConfig);
}
}
@@ -1902,6 +1912,12 @@
mWinAnimator.hide("saved surface");
mWinAnimator.mDrawState = WindowStateAnimator.NO_SURFACE;
setHasSurface(false);
+ // The client should have disconnected at this point, but if it doesn't,
+ // we need to make sure it's disconnected. Otherwise when we reuse the surface
+ // the client can't reconnect to the buffer queue, and rendering will fail.
+ if (mWinAnimator.mSurfaceController != null) {
+ mWinAnimator.mSurfaceController.disconnectInTransaction();
+ }
} else {
mWinAnimator.destroySurfaceLocked();
}
@@ -2055,21 +2071,30 @@
}
}
+ /**
+ * Update our current configurations, based on task configuration.
+ *
+ * @return A configuration suitable for sending to the client.
+ */
+ private Configuration updateConfiguration() {
+ final Task task = getTask();
+ final Configuration overrideConfig =
+ (task != null) ? task.mOverrideConfig : Configuration.EMPTY;
+ final boolean configChanged = isConfigChanged();
+ if ((DEBUG_RESIZE || DEBUG_ORIENTATION || DEBUG_CONFIGURATION) && configChanged) {
+ Slog.i(TAG, "Sending new config to window " + this + ": " +
+ " / config=" + mService.mCurConfiguration + " overrideConfig=" + overrideConfig);
+ }
+ setConfiguration(mService.mCurConfiguration, overrideConfig);
+ return mMergedConfiguration;
+ }
+
void reportResized() {
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "wm.reportResized_" + getWindowTag());
try {
if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG, "Reporting new frame to " + this
+ ": " + mCompatFrame);
- final boolean configChanged = isConfigChanged();
- final Task task = getTask();
- final Configuration overrideConfig =
- (task != null) ? task.mOverrideConfig : Configuration.EMPTY;
- if ((DEBUG_RESIZE || DEBUG_ORIENTATION || DEBUG_CONFIGURATION) && configChanged) {
- Slog.i(TAG, "Sending new config to window " + this + ": "
- + " / config="
- + mService.mCurConfiguration + " overrideConfig=" + overrideConfig);
- }
- setConfiguration(mService.mCurConfiguration, overrideConfig);
+ final Configuration newConfig = isConfigChanged() ? updateConfiguration() : null;
if (DEBUG_ORIENTATION && mWinAnimator.mDrawState == WindowStateAnimator.DRAW_PENDING)
Slog.i(TAG, "Resizing " + this + " WITH DRAW PENDING");
@@ -2080,7 +2105,6 @@
final Rect stableInsets = mLastStableInsets;
final Rect outsets = mLastOutsets;
final boolean reportDraw = mWinAnimator.mDrawState == WindowStateAnimator.DRAW_PENDING;
- final Configuration newConfig = configChanged ? mConfiguration : null;
if (mAttrs.type != WindowManager.LayoutParams.TYPE_APPLICATION_STARTING
&& mClient instanceof IWindow.Stub) {
// To prevent deadlock simulate one-way call if win.mClient is a local object.
@@ -2479,7 +2503,8 @@
final int ph = mContainingFrame.height();
final Task task = getTask();
final boolean nonFullscreenTask = task != null && !task.isFullscreen();
-
+ final boolean fitToDisplay = task != null &&
+ !task.isFloating();
float x, y;
int w,h;
@@ -2536,7 +2561,17 @@
(int) (y + mAttrs.verticalMargin * ph), mFrame);
// Now make sure the window fits in the overall display frame.
- Gravity.applyDisplay(mAttrs.gravity, mDisplayFrame, mFrame);
+ if (fitToDisplay) {
+ Gravity.applyDisplay(mAttrs.gravity, mDisplayFrame, mFrame);
+ }
+
+ // We need to make sure we update the CompatFrame as it is used for
+ // cropping decisions, etc, on systems where we lack a decor layer.
+ mCompatFrame.set(mFrame);
+ if (mEnforceSizeCompat) {
+ // See comparable block in computeFrameLw.
+ mCompatFrame.scale(mInvGlobalScale);
+ }
}
boolean isChildWindow() {
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index 02f9aa1..c1ff96e 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -20,6 +20,7 @@
import static android.view.WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
import static android.view.WindowManager.LayoutParams.FLAG_SCALED;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYERS;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT_REPEATS;
@@ -467,9 +468,8 @@
return;
}
- if (WindowManagerService.localLOGV) Slog.v(
- TAG, "Exit animation finished in " + this
- + ": remove=" + mWin.mRemoveOnExit);
+ if (WindowManagerService.localLOGV || DEBUG_ADD_REMOVE) Slog.v(TAG,
+ "Exit animation finished in " + this + ": remove=" + mWin.mRemoveOnExit);
mWin.mDestroying = true;
@@ -1115,11 +1115,11 @@
}
}
- void updateSurfaceWindowCrop(final boolean recoveringMemory) {
+ Rect calculateSurfaceWindowCrop() {
final WindowState w = mWin;
final DisplayContent displayContent = w.getDisplayContent();
if (displayContent == null) {
- return;
+ return null;
}
final DisplayInfo displayInfo = displayContent.getDisplayInfo();
if (DEBUG_WINDOW_CROP) Slog.d(TAG, "Updating crop for window: " + w + ", " + "mLastCrop=" +
@@ -1187,7 +1187,7 @@
clipRect.offset(attrs.surfaceInsets.left, attrs.surfaceInsets.top);
adjustCropToStackBounds(w, clipRect, isFreeformResizing);
- if (DEBUG_WINDOW_CROP) Slog.d(TAG, "Clip rect after stack adjustment=" + mClipRect);
+ if (DEBUG_WINDOW_CROP) Slog.d(TAG, "Clip rect after stack adjustment=" + clipRect);
w.transformFromScreenToSurfaceSpace(clipRect);
@@ -1196,6 +1196,10 @@
clipRect.setEmpty();
}
+ return clipRect;
+ }
+
+ void updateSurfaceWindowCrop(Rect clipRect, boolean recoveringMemory) {
if (!clipRect.equals(mLastClipRect)) {
mLastClipRect.set(clipRect);
mSurfaceController.setCropInTransaction(clipRect, recoveringMemory);
@@ -1237,6 +1241,7 @@
w.mFrame.left + mWin.mXOffset - w.getAttrs().surfaceInsets.left;
final int frameY = isFreeformResizing ? (int) mSurfaceController.getY() :
w.mFrame.top + mWin.mYOffset - w.getAttrs().surfaceInsets.top;
+
// We need to do some acrobatics with surface position, because their clip region is
// relative to the inside of the surface, but the stack bounds aren't.
clipRect.left = Math.max(0,
@@ -1251,14 +1256,44 @@
void setSurfaceBoundariesLocked(final boolean recoveringMemory) {
final WindowState w = mWin;
+ final Task task = w.getTask();
mTmpSize.set(w.mShownPosition.x, w.mShownPosition.y, 0, 0);
calculateSurfaceBounds(w, w.getAttrs());
- mSurfaceController.setPositionInTransaction(mTmpSize.left, mTmpSize.top, recoveringMemory);
+ float extraHScale = (float) 1.0;
+ float extraVScale = (float) 1.0;
- mSurfaceController.setMatrixInTransaction(mDsDx * w.mHScale, mDtDx * w.mVScale,
- mDsDy * w.mHScale, mDtDy * w.mVScale, recoveringMemory);
+ final Rect crop = calculateSurfaceWindowCrop();
+ if (task != null && task.mStack.getForceScaleToCrop()) {
+ extraHScale = crop.width() / (float)mTmpSize.width();
+ extraVScale = crop.height() / (float)mTmpSize.height();
+
+ // In the case of ForceScaleToCrop we scale entire tasks together,
+ // and so we need to scale our offsets relative to the task bounds
+ // or parent and child windows would fall out of alignment.
+ int posX = (int) (mTmpSize.left - w.mAttrs.x * (1 - extraHScale));
+ int posY = (int) (mTmpSize.top - w.mAttrs.y * (1 - extraVScale));
+ posX += w.getAttrs().surfaceInsets.left * (1 - extraHScale);
+ posY += w.getAttrs().surfaceInsets.top * (1 - extraVScale);
+ mSurfaceController.setPositionInTransaction(posX, posY, recoveringMemory);
+
+ // Since we are scaled to fit in our previously desired crop, we can now
+ // expose the whole window in buffer space, and not risk extending
+ // past where the system would have cropped us
+ crop.set(0, 0, mTmpSize.width(), mTmpSize.height());
+ updateSurfaceWindowCrop(crop, recoveringMemory);
+ } else {
+ mSurfaceController.setPositionInTransaction(mTmpSize.left, mTmpSize.top,
+ recoveringMemory);
+ updateSurfaceWindowCrop(crop, recoveringMemory);
+ }
+
+
+ mSurfaceController.setMatrixInTransaction(mDsDx * w.mHScale * extraHScale,
+ mDtDx * w.mVScale * extraVScale,
+ mDsDy * w.mHScale * extraHScale,
+ mDtDy * w.mVScale * extraVScale, recoveringMemory);
mSurfaceResized = mSurfaceController.setSizeInTransaction(
mTmpSize.width(), mTmpSize.height(),
recoveringMemory);
@@ -1270,7 +1305,6 @@
w.applyDimLayerIfNeeded();
}
- updateSurfaceWindowCrop(recoveringMemory);
}
void prepareSurfaceLocked(final boolean recoveringMemory) {
@@ -1409,7 +1443,7 @@
SurfaceControl.openTransaction();
mSurfaceController.setPositionInTransaction(mWin.mFrame.left + left,
mWin.mFrame.top + top, false);
- updateSurfaceWindowCrop(false);
+ updateSurfaceWindowCrop(calculateSurfaceWindowCrop(), false);
} catch (RuntimeException e) {
Slog.w(TAG, "Error positioning surface of " + mWin
+ " pos=(" + left + "," + top + ")", e);
diff --git a/services/core/java/com/android/server/wm/WindowSurfaceController.java b/services/core/java/com/android/server/wm/WindowSurfaceController.java
index 2972a24..fb07512 100644
--- a/services/core/java/com/android/server/wm/WindowSurfaceController.java
+++ b/services/core/java/com/android/server/wm/WindowSurfaceController.java
@@ -138,7 +138,7 @@
void destroyInTransaction() {
// if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) {
- Slog.i(TAG, "Destroying surface " + this + " called by " + Debug.getCallers(4));
+ Slog.i(TAG, "Destroying surface " + this + " called by " + Debug.getCallers(8));
// }
try {
if (mSurfaceControl != null) {
@@ -152,6 +152,20 @@
}
}
+ void disconnectInTransaction() {
+ if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) {
+ Slog.i(TAG, "Disconnecting client: " + this);
+ }
+
+ try {
+ if (mSurfaceControl != null) {
+ mSurfaceControl.disconnect();
+ }
+ } catch (RuntimeException e) {
+ Slog.w(TAG, "Error disconnecting surface in: " + this, e);
+ }
+ }
+
void setCropInTransaction(Rect clipRect, boolean recoveringMemory) {
if (SHOW_TRANSACTIONS) logSurface(
"CROP " + clipRect.toShortString(), null);
diff --git a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
index 856d30a..e3955fe 100644
--- a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
+++ b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
@@ -651,6 +651,7 @@
for (int i = windows.size() - 1; i >= 0; i--) {
WindowState w = windows.get(i);
+ final Task task = w.getTask();
final boolean obscuredChanged = w.mObscured != mObscured;
// Update effect.
@@ -683,7 +684,8 @@
final boolean adjustedForMinimizedDockedStack = w.getTask() != null &&
w.getTask().mStack.isAdjustedForMinimizedDockedStack();
if ((w.mAttrs.privateFlags & PRIVATE_FLAG_NO_MOVE_ANIMATION) == 0
- && !w.isDragResizing() && !adjustedForMinimizedDockedStack) {
+ && !w.isDragResizing() && !adjustedForMinimizedDockedStack
+ && (task == null || !w.getTask().mStack.getFreezeMovementAnimations())) {
winAnimator.setMoveAnimation(left, top);
}
diff --git a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
index c97323c..aa14fff 100644
--- a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
+++ b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
@@ -140,7 +140,7 @@
ALOGD("Unknown constellation type with Svid = %d.", info.svid);
info.constellation = GNSS_CONSTELLATION_UNKNOWN;
}
- info.snr = sv_status->sv_list[i].snr;
+ info.c_n0_dbhz = sv_status->sv_list[i].snr;
info.elevation = sv_status->sv_list[i].elevation;
info.azimuth = sv_status->sv_list[i].azimuth;
info.flags = GNSS_SV_FLAGS_NONE;
@@ -698,12 +698,12 @@
}
static jint android_location_GnssLocationProvider_read_sv_status(JNIEnv* env, jobject /* obj */,
- jintArray svidWithFlagArray, jfloatArray snrArray, jfloatArray elevArray,
+ jintArray svidWithFlagArray, jfloatArray cn0Array, jfloatArray elevArray,
jfloatArray azumArray)
{
// this should only be called from within a call to reportSvStatus
jint* svidWithFlags = env->GetIntArrayElements(svidWithFlagArray, 0);
- jfloat* snrs = env->GetFloatArrayElements(snrArray, 0);
+ jfloat* cn0s = env->GetFloatArrayElements(cn0Array, 0);
jfloat* elev = env->GetFloatArrayElements(elevArray, 0);
jfloat* azim = env->GetFloatArrayElements(azumArray, 0);
@@ -713,13 +713,13 @@
svidWithFlags[i] = (info.svid << SVID_SHIFT_WIDTH) |
(info.constellation << CONSTELLATION_TYPE_SHIFT_WIDTH) |
info.flags;
- snrs[i] = info.snr;
+ cn0s[i] = info.c_n0_dbhz;
elev[i] = info.elevation;
azim[i] = info.azimuth;
}
env->ReleaseIntArrayElements(svidWithFlagArray, svidWithFlags, 0);
- env->ReleaseFloatArrayElements(snrArray, snrs, 0);
+ env->ReleaseFloatArrayElements(cn0Array, cn0s, 0);
env->ReleaseFloatArrayElements(elevArray, elev, 0);
env->ReleaseFloatArrayElements(azumArray, azim, 0);
return (jint) sGnssSvListSize;
@@ -1095,7 +1095,9 @@
JavaObject object(env, "android/location/GnssClock");
GpsClockFlags flags = clock->flags;
- SET_IF(GNSS_CLOCK_HAS_LEAP_SECOND, LeapSecond, clock->leap_second);
+ SET_IF(GNSS_CLOCK_HAS_LEAP_SECOND,
+ LeapSecond,
+ static_cast<int32_t>(clock->leap_second));
// GnssClock only supports the more effective HW_CLOCK type, so type
// handling and documentation complexity has been removed. To convert the
@@ -1122,18 +1124,18 @@
break;
}
- SET(TimeInNs, clock->time_ns);
+ SET(TimeNanos, clock->time_ns);
SET_IF(GNSS_CLOCK_HAS_TIME_UNCERTAINTY,
- TimeUncertaintyInNs,
+ TimeUncertaintyNanos,
clock->time_uncertainty_ns);
- SET_IF(GNSS_CLOCK_HAS_FULL_BIAS, FullBiasInNs, clock->full_bias_ns);
- SET_IF(GNSS_CLOCK_HAS_BIAS, BiasInNs, clock->bias_ns);
+ SET_IF(GNSS_CLOCK_HAS_FULL_BIAS, FullBiasNanos, clock->full_bias_ns);
+ SET_IF(GNSS_CLOCK_HAS_BIAS, BiasNanos, clock->bias_ns);
SET_IF(GNSS_CLOCK_HAS_BIAS_UNCERTAINTY,
- BiasUncertaintyInNs,
+ BiasUncertaintyNanos,
clock->bias_uncertainty_ns);
- SET_IF(GNSS_CLOCK_HAS_DRIFT, DriftInNsPerSec, clock->drift_nsps);
+ SET_IF(GNSS_CLOCK_HAS_DRIFT, DriftNanosPerSecond, clock->drift_nsps);
SET_IF(GNSS_CLOCK_HAS_DRIFT_UNCERTAINTY,
- DriftUncertaintyInNsPerSec,
+ DriftUncertaintyNanosPerSecond,
clock->drift_uncertainty_nsps);
return object.get();
@@ -1143,20 +1145,21 @@
JavaObject object(env, "android/location/GnssClock");
GpsClockFlags flags = clock->flags;
- SET_IF(GNSS_CLOCK_HAS_LEAP_SECOND, LeapSecond, clock->leap_second);
- SET(Type, static_cast<uint8_t>(GPS_CLOCK_TYPE_LOCAL_HW_TIME));
- SET(TimeInNs, clock->time_ns);
+ SET_IF(GNSS_CLOCK_HAS_LEAP_SECOND,
+ LeapSecond,
+ static_cast<int32_t>(clock->leap_second));
+ SET(TimeNanos, clock->time_ns);
SET_IF(GNSS_CLOCK_HAS_TIME_UNCERTAINTY,
- TimeUncertaintyInNs,
+ TimeUncertaintyNanos,
clock->time_uncertainty_ns);
- SET_IF(GNSS_CLOCK_HAS_FULL_BIAS, FullBiasInNs, clock->full_bias_ns);
- SET_IF(GNSS_CLOCK_HAS_BIAS, BiasInNs, clock->bias_ns);
+ SET_IF(GNSS_CLOCK_HAS_FULL_BIAS, FullBiasNanos, clock->full_bias_ns);
+ SET_IF(GNSS_CLOCK_HAS_BIAS, BiasNanos, clock->bias_ns);
SET_IF(GNSS_CLOCK_HAS_BIAS_UNCERTAINTY,
- BiasUncertaintyInNs,
+ BiasUncertaintyNanos,
clock->bias_uncertainty_ns);
- SET_IF(GNSS_CLOCK_HAS_DRIFT, DriftInNsPerSec, clock->drift_nsps);
+ SET_IF(GNSS_CLOCK_HAS_DRIFT, DriftNanosPerSecond, clock->drift_nsps);
SET_IF(GNSS_CLOCK_HAS_DRIFT_UNCERTAINTY,
- DriftUncertaintyInNsPerSec,
+ DriftUncertaintyNanosPerSecond,
clock->drift_uncertainty_nsps);
SET(HardwareClockDiscontinuityCount, clock->hw_clock_discontinuity_count);
@@ -1168,41 +1171,30 @@
GpsMeasurement* measurement) {
JavaObject object(env, "android/location/GnssMeasurement");
GpsMeasurementFlags flags = measurement->flags;
- SET(Svid, static_cast<int16_t>(measurement->prn));
+ SET(Svid, static_cast<int32_t>(measurement->prn));
if (measurement->prn >= 1 || measurement->prn <= 32) {
- SET(ConstellationType, static_cast<uint8_t>(GNSS_CONSTELLATION_GPS));
+ SET(ConstellationType, static_cast<int32_t>(GNSS_CONSTELLATION_GPS));
} else {
ALOGD("Unknown constellation type with Svid = %d.", measurement->prn);
SET(ConstellationType,
- static_cast<uint8_t>(GNSS_CONSTELLATION_UNKNOWN));
+ static_cast<int32_t>(GNSS_CONSTELLATION_UNKNOWN));
}
- SET(TimeOffsetInNs, measurement->time_offset_ns);
- SET(State, measurement->state);
- SET(ReceivedSvTimeInNs, measurement->received_gps_tow_ns);
- SET(ReceivedSvTimeUncertaintyInNs,
+ SET(TimeOffsetNanos, measurement->time_offset_ns);
+ SET(State, static_cast<int32_t>(measurement->state));
+ SET(ReceivedSvTimeNanos, measurement->received_gps_tow_ns);
+ SET(ReceivedSvTimeUncertaintyNanos,
measurement->received_gps_tow_uncertainty_ns);
- SET(Cn0InDbHz, measurement->c_n0_dbhz);
- SET(PseudorangeRateInMetersPerSec, measurement->pseudorange_rate_mps);
- SET(PseudorangeRateUncertaintyInMetersPerSec,
+ SET(Cn0DbHz, measurement->c_n0_dbhz);
+ SET(PseudorangeRateMetersPerSecond, measurement->pseudorange_rate_mps);
+ SET(PseudorangeRateUncertaintyMetersPerSecond,
measurement->pseudorange_rate_uncertainty_mps);
- SET(AccumulatedDeltaRangeState, measurement->accumulated_delta_range_state);
- SET(AccumulatedDeltaRangeInMeters, measurement->accumulated_delta_range_m);
- SET(AccumulatedDeltaRangeUncertaintyInMeters,
+ SET(AccumulatedDeltaRangeState,
+ static_cast<int32_t>(measurement->accumulated_delta_range_state));
+ SET(AccumulatedDeltaRangeMeters, measurement->accumulated_delta_range_m);
+ SET(AccumulatedDeltaRangeUncertaintyMeters,
measurement->accumulated_delta_range_uncertainty_m);
- SET_IF(GNSS_MEASUREMENT_HAS_PSEUDORANGE,
- PseudorangeInMeters,
- measurement->pseudorange_m);
- SET_IF(GNSS_MEASUREMENT_HAS_PSEUDORANGE_UNCERTAINTY,
- PseudorangeUncertaintyInMeters,
- measurement->pseudorange_uncertainty_m);
- SET_IF(GNSS_MEASUREMENT_HAS_CODE_PHASE,
- CodePhaseInChips,
- measurement->code_phase_chips);
- SET_IF(GNSS_MEASUREMENT_HAS_CODE_PHASE_UNCERTAINTY,
- CodePhaseUncertaintyInChips,
- measurement->code_phase_uncertainty_chips);
SET_IF(GNSS_MEASUREMENT_HAS_CARRIER_FREQUENCY,
- CarrierFrequencyInHz,
+ CarrierFrequencyHz,
measurement->carrier_frequency_hz);
SET_IF(GNSS_MEASUREMENT_HAS_CARRIER_CYCLES,
CarrierCycles,
@@ -1213,33 +1205,8 @@
SET_IF(GNSS_MEASUREMENT_HAS_CARRIER_PHASE_UNCERTAINTY,
CarrierPhaseUncertainty,
measurement->carrier_phase_uncertainty);
- SET(LossOfLock, measurement->loss_of_lock);
- SET_IF(GNSS_MEASUREMENT_HAS_BIT_NUMBER, BitNumber, measurement->bit_number);
- SET_IF(GNSS_MEASUREMENT_HAS_TIME_FROM_LAST_BIT,
- TimeFromLastBitInMs,
- measurement->time_from_last_bit_ms);
- SET_IF(GNSS_MEASUREMENT_HAS_DOPPLER_SHIFT,
- DopplerShiftInHz,
- measurement->doppler_shift_hz);
- SET_IF(GNSS_MEASUREMENT_HAS_DOPPLER_SHIFT_UNCERTAINTY,
- DopplerShiftUncertaintyInHz,
- measurement->doppler_shift_uncertainty_hz);
SET(MultipathIndicator, measurement->multipath_indicator);
SET_IF(GNSS_MEASUREMENT_HAS_SNR, SnrInDb, measurement->snr_db);
- SET_IF(GNSS_MEASUREMENT_HAS_ELEVATION,
- ElevationInDeg,
- measurement->elevation_deg);
- SET_IF(GNSS_MEASUREMENT_HAS_ELEVATION_UNCERTAINTY,
- ElevationUncertaintyInDeg,
- measurement->elevation_uncertainty_deg);
- SET_IF(GNSS_MEASUREMENT_HAS_AZIMUTH,
- AzimuthInDeg,
- measurement->azimuth_deg);
- SET_IF(GNSS_MEASUREMENT_HAS_AZIMUTH_UNCERTAINTY,
- AzimuthUncertaintyInDeg,
- measurement->azimuth_uncertainty_deg);
- SET(UsedInFix,
- (flags & GNSS_MEASUREMENT_HAS_USED_IN_FIX) && measurement->used_in_fix);
return object.get();
}
@@ -1250,34 +1217,23 @@
GpsMeasurementFlags flags = measurement->flags;
SET(Svid, measurement->svid);
- SET(ConstellationType, measurement->constellation);
- SET(TimeOffsetInNs, measurement->time_offset_ns);
- SET(State, measurement->state);
- SET(ReceivedSvTimeInNs, measurement->received_sv_time_in_ns);
- SET(ReceivedSvTimeUncertaintyInNs,
+ SET(ConstellationType, static_cast<int32_t>(measurement->constellation));
+ SET(TimeOffsetNanos, measurement->time_offset_ns);
+ SET(State, static_cast<int32_t>(measurement->state));
+ SET(ReceivedSvTimeNanos, measurement->received_sv_time_in_ns);
+ SET(ReceivedSvTimeUncertaintyNanos,
measurement->received_sv_time_uncertainty_in_ns);
- SET(Cn0InDbHz, measurement->c_n0_dbhz);
- SET(PseudorangeRateInMetersPerSec, measurement->pseudorange_rate_mps);
- SET(PseudorangeRateUncertaintyInMetersPerSec,
+ SET(Cn0DbHz, measurement->c_n0_dbhz);
+ SET(PseudorangeRateMetersPerSecond, measurement->pseudorange_rate_mps);
+ SET(PseudorangeRateUncertaintyMetersPerSecond,
measurement->pseudorange_rate_uncertainty_mps);
- SET(AccumulatedDeltaRangeState, measurement->accumulated_delta_range_state);
- SET(AccumulatedDeltaRangeInMeters, measurement->accumulated_delta_range_m);
- SET(AccumulatedDeltaRangeUncertaintyInMeters,
+ SET(AccumulatedDeltaRangeState,
+ static_cast<int32_t>(measurement->accumulated_delta_range_state));
+ SET(AccumulatedDeltaRangeMeters, measurement->accumulated_delta_range_m);
+ SET(AccumulatedDeltaRangeUncertaintyMeters,
measurement->accumulated_delta_range_uncertainty_m);
- SET_IF(GNSS_MEASUREMENT_HAS_PSEUDORANGE,
- PseudorangeInMeters,
- measurement->pseudorange_m);
- SET_IF(GNSS_MEASUREMENT_HAS_PSEUDORANGE_UNCERTAINTY,
- PseudorangeUncertaintyInMeters,
- measurement->pseudorange_uncertainty_m);
- SET_IF(GNSS_MEASUREMENT_HAS_CODE_PHASE,
- CodePhaseInChips,
- measurement->code_phase_chips);
- SET_IF(GNSS_MEASUREMENT_HAS_CODE_PHASE_UNCERTAINTY,
- CodePhaseUncertaintyInChips,
- measurement->code_phase_uncertainty_chips);
SET_IF(GNSS_MEASUREMENT_HAS_CARRIER_FREQUENCY,
- CarrierFrequencyInHz,
+ CarrierFrequencyHz,
measurement->carrier_frequency_hz);
SET_IF(GNSS_MEASUREMENT_HAS_CARRIER_CYCLES,
CarrierCycles,
@@ -1288,32 +1244,8 @@
SET_IF(GNSS_MEASUREMENT_HAS_CARRIER_PHASE_UNCERTAINTY,
CarrierPhaseUncertainty,
measurement->carrier_phase_uncertainty);
- SET_IF(GNSS_MEASUREMENT_HAS_BIT_NUMBER, BitNumber, measurement->bit_number);
- SET_IF(GNSS_MEASUREMENT_HAS_TIME_FROM_LAST_BIT,
- TimeFromLastBitInMs,
- measurement->time_from_last_bit_ms);
- SET_IF(GNSS_MEASUREMENT_HAS_DOPPLER_SHIFT,
- DopplerShiftInHz,
- measurement->doppler_shift_hz);
- SET_IF(GNSS_MEASUREMENT_HAS_DOPPLER_SHIFT_UNCERTAINTY,
- DopplerShiftUncertaintyInHz,
- measurement->doppler_shift_uncertainty_hz);
SET(MultipathIndicator, measurement->multipath_indicator);
SET_IF(GNSS_MEASUREMENT_HAS_SNR, SnrInDb, measurement->snr_db);
- SET_IF(GNSS_MEASUREMENT_HAS_ELEVATION,
- ElevationInDeg,
- measurement->elevation_deg);
- SET_IF(GNSS_MEASUREMENT_HAS_ELEVATION_UNCERTAINTY,
- ElevationUncertaintyInDeg,
- measurement->elevation_uncertainty_deg);
- SET_IF(GNSS_MEASUREMENT_HAS_AZIMUTH,
- AzimuthInDeg,
- measurement->azimuth_deg);
- SET_IF(GNSS_MEASUREMENT_HAS_AZIMUTH_UNCERTAINTY,
- AzimuthUncertaintyInDeg,
- measurement->azimuth_uncertainty_deg);
- SET(UsedInFix,
- (flags & GNSS_MEASUREMENT_HAS_USED_IN_FIX) && measurement->used_in_fix);
return object.get();
}
@@ -1493,21 +1425,22 @@
return NULL;
}
JavaObject object(env, "android/location/GnssNavigationMessage");
- SET(Svid, static_cast<int16_t>(message->prn));
+ SET(Svid, static_cast<int32_t>(message->prn));
if (message->prn >=1 && message->prn <= 32) {
- SET(ConstellationType, static_cast<uint8_t>(GNSS_CONSTELLATION_GPS));
+ SET(ConstellationType, static_cast<int32_t>(GNSS_CONSTELLATION_GPS));
// Legacy driver doesn't set the higher byte to constellation type
// correctly. Set the higher byte to 'GPS'.
- SET(Type, static_cast<int16_t>(message->type | 0x0100));
+ SET(Type, static_cast<int32_t>(message->type | 0x0100));
} else {
ALOGD("Unknown constellation type with Svid = %d.", message->prn);
SET(ConstellationType,
- static_cast<uint8_t>(GNSS_CONSTELLATION_UNKNOWN));
- SET(Type, static_cast<int16_t>(GNSS_NAVIGATION_MESSAGE_TYPE_UNKNOWN));
+ static_cast<int32_t>(GNSS_CONSTELLATION_UNKNOWN));
+ SET(Type, static_cast<int32_t>(GNSS_NAVIGATION_MESSAGE_TYPE_UNKNOWN));
}
- SET(MessageId, message->message_id);
- SET(SubmessageId, message->submessage_id);
+ SET(MessageId, static_cast<int32_t>(message->message_id));
+ SET(SubmessageId, static_cast<int32_t>(message->submessage_id));
object.callSetter("setData", data, dataLength);
+ SET(Status, static_cast<int32_t>(message->status));
return object.get();
}
@@ -1520,11 +1453,12 @@
return NULL;
}
JavaObject object(env, "android/location/GnssNavigationMessage");
- SET(Type, message->type);
- SET(Svid, message->svid);
- SET(MessageId, message->message_id);
- SET(SubmessageId, message->submessage_id);
+ SET(Type, static_cast<int32_t>(message->type));
+ SET(Svid, static_cast<int32_t>(message->svid));
+ SET(MessageId, static_cast<int32_t>(message->message_id));
+ SET(SubmessageId, static_cast<int32_t>(message->submessage_id));
object.callSetter("setData", data, dataLength);
+ SET(Status, static_cast<int32_t>(message->status));
return object.get();
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 0252ea4..1490109 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -5530,7 +5530,8 @@
Preconditions.checkNotNull(packageName, "packageName is null");
final int callingUid = mInjector.binderGetCallingUid();
try {
- int uid = mContext.getPackageManager().getPackageUidAsUser(packageName, 0);
+ int uid = mContext.getPackageManager().getPackageUidAsUser(packageName,
+ UserHandle.getUserId(callingUid));
if (uid != callingUid) {
throw new SecurityException("Invalid packageName");
}
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 0ece6aa..b8c31e3 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -431,6 +431,24 @@
mPackageManager = mSystemContext.getPackageManager();
Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
+ // Manages A/B OTA dexopting. This is a bootstrap service as we need it to rename
+ // A/B artifacts after boot, before anything else might touch/need them.
+ // Note: this isn't needed during decryption (we don't have /data anyways).
+ if (!mOnlyCore) {
+ boolean disableOtaDexopt = SystemProperties.getBoolean("config.disable_otadexopt",
+ false);
+ if (!disableOtaDexopt) {
+ traceBeginAndSlog("StartOtaDexOptService");
+ try {
+ OtaDexoptService.main(mSystemContext, mPackageManagerService);
+ } catch (Throwable e) {
+ reportWtf("starting OtaDexOptService", e);
+ } finally {
+ Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
+ }
+ }
+ }
+
traceBeginAndSlog("StartUserManagerService");
ServiceManager.addService(Context.USER_SERVICE, UserManagerService.getInstance());
Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
@@ -1036,6 +1054,7 @@
traceBeginAndSlog("StartNetworkTimeUpdateService");
try {
networkTimeUpdater = new NetworkTimeUpdateService(context);
+ ServiceManager.addService("network_time_update_service", networkTimeUpdater);
} catch (Throwable e) {
reportWtf("starting NetworkTimeUpdate service", e);
}
@@ -1123,19 +1142,6 @@
reportWtf("starting BackgroundDexOptService", e);
}
Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
-
- // Manages A/B OTA dexopting.
- boolean disableOtaDexopt = SystemProperties.getBoolean("config.disable_otadexopt",
- false);
- if (!disableOtaDexopt) {
- traceBeginAndSlog("StartOtaDexOptService");
- try {
- OtaDexoptService.main(mSystemContext, mPackageManagerService);
- } catch (Throwable e) {
- reportWtf("starting BackgroundDexOptService", e);
- }
- Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
- }
}
mSystemServiceManager.startService(LauncherAppsService.class);
diff --git a/services/net/java/android/net/ip/IpManager.java b/services/net/java/android/net/ip/IpManager.java
index 46ecc50..afae956 100644
--- a/services/net/java/android/net/ip/IpManager.java
+++ b/services/net/java/android/net/ip/IpManager.java
@@ -66,9 +66,6 @@
private static final boolean DBG = true;
private static final boolean VDBG = false;
- private static final boolean NO_CALLBACKS = false;
- private static final boolean SEND_CALLBACKS = true;
-
// For message logging.
private static final Class[] sMessageClasses = { IpManager.class, DhcpClient.class };
private static final SparseArray<String> sWhatToString =
@@ -98,6 +95,10 @@
public void onProvisioningSuccess(LinkProperties newLp) {}
public void onProvisioningFailure(LinkProperties newLp) {}
+ // This is called whenever 464xlat is being enabled or disabled (i.e.
+ // started or stopped).
+ public void on464XlatChange(boolean enabled) {}
+
// Invoked on LinkProperties changes.
public void onLinkPropertiesChange(LinkProperties newLp) {}
@@ -207,6 +208,13 @@
private static final int MAX_LOG_RECORDS = 1000;
+ private static final boolean NO_CALLBACKS = false;
+ private static final boolean SEND_CALLBACKS = true;
+
+ // This must match the interface prefix in clatd.c.
+ // TODO: Revert this hack once IpManager and Nat464Xlat work in concert.
+ private static final String CLAT_PREFIX = "v4-";
+
private final Object mLock = new Object();
private final State mStoppedState = new StoppedState();
private final State mStoppingState = new StoppingState();
@@ -215,6 +223,7 @@
private final String mTag;
private final Context mContext;
private final String mInterfaceName;
+ private final String mClatInterfaceName;
@VisibleForTesting
protected final Callback mCallback;
private final INetworkManagementService mNwService;
@@ -255,6 +264,7 @@
mContext = context;
mInterfaceName = ifName;
+ mClatInterfaceName = CLAT_PREFIX + ifName;
mCallback = callback;
mNwService = nwService;
@@ -265,7 +275,22 @@
public void update() {
sendMessage(EVENT_NETLINK_LINKPROPERTIES_CHANGED);
}
- });
+ }) {
+ @Override
+ public void interfaceAdded(String iface) {
+ if (mClatInterfaceName.equals(iface)) {
+ mCallback.on464XlatChange(true);
+ }
+ }
+
+ @Override
+ public void interfaceRemoved(String iface) {
+ if (mClatInterfaceName.equals(iface)) {
+ mCallback.on464XlatChange(false);
+ }
+ }
+ };
+
try {
mNwService.registerObserver(mNetlinkTracker);
} catch (RemoteException e) {
diff --git a/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java b/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java
index 5874429..69f12eb 100644
--- a/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java
@@ -59,14 +59,17 @@
import android.os.MessageQueue;
import android.os.Messenger;
import android.os.MessageQueue.IdleHandler;
+import android.os.SystemClock;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.LargeTest;
import android.test.suitebuilder.annotation.SmallTest;
import android.util.Log;
import android.util.LogPrinter;
+import com.android.internal.util.WakeupMessage;
import com.android.server.connectivity.NetworkAgentInfo;
import com.android.server.connectivity.NetworkMonitor;
+import com.android.server.net.NetworkPinner;
import java.net.InetAddress;
import java.util.concurrent.CountDownLatch;
@@ -87,10 +90,30 @@
private BroadcastInterceptingContext mServiceContext;
private WrappedConnectivityService mService;
- private ConnectivityManager mCm;
+ private WrappedConnectivityManager mCm;
private MockNetworkAgent mWiFiNetworkAgent;
private MockNetworkAgent mCellNetworkAgent;
+ // This class exists to test bindProcessToNetwork and getBoundNetworkForProcess. These methods
+ // do not go through ConnectivityService but talk to netd directly, so they don't automatically
+ // reflect the state of our test ConnectivityService.
+ private class WrappedConnectivityManager extends ConnectivityManager {
+ private Network mFakeBoundNetwork;
+
+ public synchronized boolean bindProcessToNetwork(Network network) {
+ mFakeBoundNetwork = network;
+ return true;
+ }
+
+ public synchronized Network getBoundNetworkForProcess() {
+ return mFakeBoundNetwork;
+ }
+
+ public WrappedConnectivityManager(Context context, ConnectivityService service) {
+ super(context, service);
+ }
+ }
+
private class MockContext extends BroadcastInterceptingContext {
MockContext(Context base) {
super(base);
@@ -484,6 +507,35 @@
}
}
+ private class FakeWakeupMessage extends WakeupMessage {
+ private static final int UNREASONABLY_LONG_WAIT = 1000;
+
+ public FakeWakeupMessage(Context context, Handler handler, String cmdName, int cmd) {
+ super(context, handler, cmdName, cmd);
+ }
+
+ @Override
+ public void schedule(long when) {
+ long delayMs = when - SystemClock.elapsedRealtime();
+ if (delayMs < 0) delayMs = 0;
+ if (delayMs > UNREASONABLY_LONG_WAIT) {
+ fail("Attempting to send msg more than " + UNREASONABLY_LONG_WAIT +
+ "ms into the future: " + delayMs);
+ }
+ mHandler.sendEmptyMessageDelayed(mCmd, delayMs);
+ }
+
+ @Override
+ public void cancel() {
+ mHandler.removeMessages(mCmd);
+ }
+
+ @Override
+ public void onAlarm() {
+ throw new AssertionError("Should never happen. Update this fake.");
+ }
+ }
+
// NetworkMonitor implementation allowing overriding of Internet connectivity probe result.
private class WrappedNetworkMonitor extends NetworkMonitor {
// HTTP response code fed back to NetworkMonitor for Internet connectivity probe.
@@ -498,6 +550,12 @@
protected int isCaptivePortal() {
return gen204ProbeResult;
}
+
+ @Override
+ protected WakeupMessage makeWakeupMessage(
+ Context context, Handler handler, String cmdName, int cmd) {
+ return new FakeWakeupMessage(context, handler, cmdName, cmd);
+ }
}
private class WrappedConnectivityService extends ConnectivityService {
@@ -575,10 +633,10 @@
int delays = 0;
while (!criteria.get()) {
try {
- Thread.sleep(100);
+ Thread.sleep(50);
} catch (InterruptedException e) {
}
- if (++delays == 5) fail();
+ if (++delays == 10) fail();
}
}
@@ -594,6 +652,8 @@
public void setUp() throws Exception {
super.setUp();
+ NetworkMonitor.SetDefaultLingerTime(120);
+
// InstrumentationTestRunner prepares a looper, but AndroidJUnitRunner does not.
// http://b/25897652 .
if (Looper.myLooper() == null) {
@@ -607,7 +667,8 @@
mock(INetworkPolicyManager.class));
mService.systemReady();
- mCm = new ConnectivityManager(getContext(), mService);
+ mCm = new WrappedConnectivityManager(getContext(), mService);
+ mCm.bindProcessToNetwork(null);
}
private int transportToLegacyType(int transport) {
@@ -674,8 +735,6 @@
@LargeTest
public void testLingering() throws Exception {
- // Decrease linger timeout to the minimum allowed by AlarmManagerService.
- NetworkMonitor.SetDefaultLingerTime(5000);
verifyNoNetwork();
mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
@@ -702,10 +761,8 @@
assertTrue(mCm.getAllNetworks()[0].equals(mCellNetworkAgent.getNetwork()) ||
mCm.getAllNetworks()[1].equals(mCellNetworkAgent.getNetwork()));
// Test cellular linger timeout.
- try {
- Thread.sleep(6000);
- } catch (InterruptedException e) {
- }
+ waitFor(new Criteria() {
+ public boolean get() { return mCm.getAllNetworks().length == 1; } });
verifyActiveNetwork(TRANSPORT_WIFI);
assertEquals(1, mCm.getAllNetworks().length);
assertEquals(mCm.getAllNetworks()[0], mCm.getActiveNetwork());
@@ -1543,4 +1600,103 @@
String url = mCm.getCaptivePortalServerUrl();
assertEquals("http://connectivitycheck.gstatic.com/generate_204", url);
}
+
+ private static class TestNetworkPinner extends NetworkPinner {
+ public static boolean awaitPin(int timeoutMs) {
+ synchronized(sLock) {
+ if (sNetwork == null) {
+ try {
+ sLock.wait(timeoutMs);
+ } catch (InterruptedException e) {}
+ }
+ return sNetwork != null;
+ }
+ }
+
+ public static boolean awaitUnpin(int timeoutMs) {
+ synchronized(sLock) {
+ if (sNetwork != null) {
+ try {
+ sLock.wait(timeoutMs);
+ } catch (InterruptedException e) {}
+ }
+ return sNetwork == null;
+ }
+ }
+ }
+
+ private void assertPinnedToWifiWithCellDefault() {
+ assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getBoundNetworkForProcess());
+ assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
+ }
+
+ private void assertPinnedToWifiWithWifiDefault() {
+ assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getBoundNetworkForProcess());
+ assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
+ }
+
+ private void assertNotPinnedToWifi() {
+ assertNull(mCm.getBoundNetworkForProcess());
+ assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
+ }
+
+ @SmallTest
+ public void testNetworkPinner() {
+ NetworkRequest wifiRequest = new NetworkRequest.Builder()
+ .addTransportType(TRANSPORT_WIFI)
+ .build();
+ assertNull(mCm.getBoundNetworkForProcess());
+
+ TestNetworkPinner.pin(mServiceContext, wifiRequest);
+ assertNull(mCm.getBoundNetworkForProcess());
+
+ mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
+ mCellNetworkAgent.connect(true);
+ mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+ mWiFiNetworkAgent.connect(false);
+
+ // When wi-fi connects, expect to be pinned.
+ assertTrue(TestNetworkPinner.awaitPin(100));
+ assertPinnedToWifiWithCellDefault();
+
+ // Disconnect and expect the pin to drop.
+ mWiFiNetworkAgent.disconnect();
+ assertTrue(TestNetworkPinner.awaitUnpin(100));
+ assertNotPinnedToWifi();
+
+ // Reconnecting does not cause the pin to come back.
+ mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+ mWiFiNetworkAgent.connect(false);
+ assertFalse(TestNetworkPinner.awaitPin(100));
+ assertNotPinnedToWifi();
+
+ // Pinning while connected causes the pin to take effect immediately.
+ TestNetworkPinner.pin(mServiceContext, wifiRequest);
+ assertTrue(TestNetworkPinner.awaitPin(100));
+ assertPinnedToWifiWithCellDefault();
+
+ // Explicitly unpin and expect to use the default network again.
+ TestNetworkPinner.unpin();
+ assertNotPinnedToWifi();
+
+ // Disconnect cell and wifi.
+ ConditionVariable cv = waitForConnectivityBroadcasts(3); // cell down, wifi up, wifi down.
+ mCellNetworkAgent.disconnect();
+ mWiFiNetworkAgent.disconnect();
+ waitFor(cv);
+
+ // Pinning takes effect even if the pinned network is the default when the pin is set...
+ TestNetworkPinner.pin(mServiceContext, wifiRequest);
+ mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+ mWiFiNetworkAgent.connect(false);
+ assertTrue(TestNetworkPinner.awaitPin(100));
+ assertPinnedToWifiWithWifiDefault();
+
+ // ... and is maintained even when that network is no longer the default.
+ cv = waitForConnectivityBroadcasts(1);
+ mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+ mCellNetworkAgent.connect(true);
+ waitFor(cv);
+ assertPinnedToWifiWithCellDefault();
+ }
}
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index 8b250f4..8da1785 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -437,7 +437,7 @@
return false;
}
} catch (RemoteException re) {
- return false;
+ throw re.rethrowFromSystemServer();
}
final long elapsedRealtime = SystemClock.elapsedRealtime();
@@ -805,6 +805,7 @@
return false;
}
} catch (RemoteException re) {
+ throw re.rethrowFromSystemServer();
}
if (isActiveDeviceAdmin(packageName, userId)) {
@@ -849,7 +850,7 @@
}
apps = slice.getList();
} catch (RemoteException e) {
- return new int[0];
+ throw e.rethrowFromSystemServer();
}
// State of each uid. Key is the uid. Value lower 16 bits is the number of apps
@@ -1258,7 +1259,7 @@
userId = ActivityManagerNative.getDefault().handleIncomingUser(Binder.getCallingPid(),
Binder.getCallingUid(), userId, false, true, "isAppInactive", null);
} catch (RemoteException re) {
- return false;
+ throw re.rethrowFromSystemServer();
}
final long token = Binder.clearCallingIdentity();
try {
@@ -1277,7 +1278,7 @@
Binder.getCallingPid(), callingUid, userId, false, true,
"setAppIdle", null);
} catch (RemoteException re) {
- return;
+ throw re.rethrowFromSystemServer();
}
getContext().enforceCallingPermission(Manifest.permission.CHANGE_APP_IDLE_STATE,
"No permission to change app idle state");
diff --git a/test-runner/src/android/test/mock/MockPackageManager.java b/test-runner/src/android/test/mock/MockPackageManager.java
index c34d4a9..e851c8d 100644
--- a/test-runner/src/android/test/mock/MockPackageManager.java
+++ b/test-runner/src/android/test/mock/MockPackageManager.java
@@ -518,6 +518,14 @@
throw new UnsupportedOperationException();
}
+ /** @hide */
+ @Override
+ public Drawable getManagedUserBadgedDrawable(Drawable drawable, Rect badgeLocation,
+ int badgeDensity) {
+ throw new UnsupportedOperationException();
+ }
+
+
@Override
public Drawable getUserBadgedIcon(Drawable icon, UserHandle user) {
throw new UnsupportedOperationException();
diff --git a/tests/HwAccelerationTest/res/drawable/default_wallpaper.jpg b/tests/HwAccelerationTest/res/drawable/default_wallpaper.jpg
deleted file mode 100644
index 5acad94..0000000
--- a/tests/HwAccelerationTest/res/drawable/default_wallpaper.jpg
+++ /dev/null
Binary files differ
diff --git a/tests/HwAccelerationTest/res/drawable/default_wallpaper.png b/tests/HwAccelerationTest/res/drawable/default_wallpaper.png
new file mode 100644
index 0000000..187a6c0
--- /dev/null
+++ b/tests/HwAccelerationTest/res/drawable/default_wallpaper.png
Binary files differ
diff --git a/tests/HwAccelerationTest/res/layout/projection_clipping.xml b/tests/HwAccelerationTest/res/layout/projection_clipping.xml
index 1f2b939..1ea9f9c 100644
--- a/tests/HwAccelerationTest/res/layout/projection_clipping.xml
+++ b/tests/HwAccelerationTest/res/layout/projection_clipping.xml
@@ -3,24 +3,32 @@
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
- <FrameLayout
+ <ScrollView
+ android:orientation="vertical"
android:translationX="50dp"
android:translationY="50dp"
android:elevation="30dp"
android:layout_width="200dp"
android:layout_height="200dp"
android:background="@drawable/round_rect_background">
- <View
- android:id="@+id/clickable1"
- android:layout_width="100dp"
- android:layout_height="100dp"
- android:background="?android:attr/selectableItemBackgroundBorderless"/>
- <View
- android:id="@+id/clickable2"
- android:translationX="50dp"
- android:translationY="10dp"
- android:layout_width="150dp"
- android:layout_height="100dp"
- android:background="?android:attr/selectableItemBackgroundBorderless"/>
- </FrameLayout>
+ <FrameLayout
+ android:layout_width="200dp"
+ android:layout_height="wrap_content">
+ <View
+ android:layout_width="200dp"
+ android:layout_height="2000dp"/>
+ <View
+ android:id="@+id/clickable1"
+ android:layout_width="100dp"
+ android:layout_height="100dp"
+ android:background="?android:attr/selectableItemBackgroundBorderless"/>
+ <View
+ android:id="@+id/clickable2"
+ android:translationX="50dp"
+ android:translationY="10dp"
+ android:layout_width="150dp"
+ android:layout_height="100dp"
+ android:background="?android:attr/selectableItemBackgroundBorderless"/>
+ </FrameLayout>
+ </ScrollView>
</LinearLayout>
diff --git a/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java b/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java
index 2a3f143..0da1bb1 100644
--- a/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java
+++ b/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java
@@ -93,11 +93,7 @@
.setSmallIcon(R.drawable.icon2)
.setContentTitle("Min priority")
.setLights(0xff0000ff, 1, 0)
- .setDefaults(Notification.DEFAULT_LIGHTS|Notification.DEFAULT_VIBRATE)
- .setSound(Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + "://" +
- getPackageName() + "/raw/ringer"))
.setPriority(Notification.PRIORITY_MIN)
- .setFullScreenIntent(makeIntent2(), false)
.build();
mNM.notify(7000, n);
}
@@ -125,11 +121,7 @@
.setSmallIcon(R.drawable.icon2)
.setContentTitle("Low priority")
.setLights(0xff0000ff, 1, 0)
- .setDefaults(Notification.DEFAULT_LIGHTS|Notification.DEFAULT_VIBRATE)
- .setSound(Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + "://" +
- getPackageName() + "/raw/ringer"))
.setPriority(Notification.PRIORITY_LOW)
- .setFullScreenIntent(makeIntent2(), false)
.build();
mNM.notify(7002, n);
}
@@ -141,11 +133,7 @@
.setSmallIcon(R.drawable.icon2)
.setContentTitle("Default priority")
.setLights(0xff0000ff, 1, 0)
- .setDefaults(Notification.DEFAULT_LIGHTS|Notification.DEFAULT_VIBRATE)
- .setSound(Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + "://" +
- getPackageName() + "/raw/ringer"))
.setPriority(Notification.PRIORITY_DEFAULT)
- .setFullScreenIntent(makeIntent2(), false)
.build();
mNM.notify(7004, n);
}
@@ -161,7 +149,6 @@
.setSound(Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + "://" +
getPackageName() + "/raw/ringer"))
.setPriority(Notification.PRIORITY_HIGH)
- .setFullScreenIntent(makeIntent2(), false)
.build();
mNM.notify(7006, n);
}
@@ -179,7 +166,7 @@
.setPriority(Notification.PRIORITY_MAX)
.setFullScreenIntent(makeIntent2(), false)
.build();
- mNM.notify(7008, n);
+ mNM.notify(7007, n);
}
},
new Test("Max priority with delay") {
@@ -202,6 +189,64 @@
mNM.notify(7008, n);
}
},
+ new Test("public notification") {
+ public void run()
+ {
+ Notification n = new Notification.Builder(NotificationTestList.this)
+ .setSmallIcon(R.drawable.icon2)
+ .setContentTitle("public notification")
+ .setDefaults(Notification.DEFAULT_LIGHTS|Notification.DEFAULT_VIBRATE)
+ .setPriority(Notification.PRIORITY_DEFAULT)
+ .setVisibility(Notification.VISIBILITY_PUBLIC)
+ .build();
+ mNM.notify(7009, n);
+ }
+ },
+ new Test("private notification, no public") {
+ public void run()
+ {
+ Notification n = new Notification.Builder(NotificationTestList.this)
+ .setSmallIcon(R.drawable.icon2)
+ .setContentTitle("private only notification")
+ .setDefaults(Notification.DEFAULT_LIGHTS|Notification.DEFAULT_VIBRATE)
+ .setPriority(Notification.PRIORITY_DEFAULT)
+ .setVisibility(Notification.VISIBILITY_PRIVATE)
+ .build();
+ mNM.notify(7010, n);
+ }
+ },
+ new Test("private notification, has public") {
+ public void run()
+ {
+ Notification n = new Notification.Builder(NotificationTestList.this)
+ .setSmallIcon(R.drawable.icon2)
+ .setContentTitle("private version of notification")
+ .setDefaults(Notification.DEFAULT_LIGHTS|Notification.DEFAULT_VIBRATE)
+ .setPriority(Notification.PRIORITY_DEFAULT)
+ .setVisibility(Notification.VISIBILITY_PRIVATE)
+ .setPublicVersion(new Notification.Builder(NotificationTestList.this)
+ .setSmallIcon(R.drawable.icon2)
+ .setContentTitle("public notification of private notification")
+ .setPriority(Notification.PRIORITY_DEFAULT)
+ .setVisibility(Notification.VISIBILITY_PUBLIC)
+ .build())
+ .build();
+ mNM.notify(7011, n);
+ }
+ },
+ new Test("secret notification") {
+ public void run()
+ {
+ Notification n = new Notification.Builder(NotificationTestList.this)
+ .setSmallIcon(R.drawable.icon2)
+ .setContentTitle("secret notification")
+ .setDefaults(Notification.DEFAULT_LIGHTS|Notification.DEFAULT_VIBRATE)
+ .setPriority(Notification.PRIORITY_DEFAULT)
+ .setVisibility(Notification.VISIBILITY_SECRET)
+ .build();
+ mNM.notify(7012, n);
+ }
+ },
new Test("Off") {
public void run() {
PowerManager pm = (PowerManager)NotificationTestList.this.getSystemService(Context.POWER_SERVICE);
diff --git a/tools/aapt/AaptAssets.cpp b/tools/aapt/AaptAssets.cpp
index 3b01827..cbd8480 100644
--- a/tools/aapt/AaptAssets.cpp
+++ b/tools/aapt/AaptAssets.cpp
@@ -373,7 +373,7 @@
void AaptLocaleValue::initFromResTable(const ResTable_config& config) {
config.unpackLanguage(language);
config.unpackRegion(region);
- if (config.localeScriptWasProvided) {
+ if (config.localeScript[0] && !config.localeScriptWasComputed) {
memcpy(script, config.localeScript, sizeof(config.localeScript));
}
@@ -388,10 +388,10 @@
if (script[0]) {
memcpy(out->localeScript, script, sizeof(out->localeScript));
- out->localeScriptWasProvided = true;
+ out->localeScriptWasComputed = false;
} else {
out->computeScript();
- out->localeScriptWasProvided = false;
+ out->localeScriptWasComputed = true;
}
if (variant[0]) {
diff --git a/tools/aapt2/Locale.cpp b/tools/aapt2/Locale.cpp
index 6acf3b0..12f56fc 100644
--- a/tools/aapt2/Locale.cpp
+++ b/tools/aapt2/Locale.cpp
@@ -253,7 +253,7 @@
void LocaleValue::initFromResTable(const ResTable_config& config) {
config.unpackLanguage(language);
config.unpackRegion(region);
- if (config.localeScriptWasProvided) {
+ if (config.localeScript[0] && !config.localeScriptWasComputed) {
memcpy(script, config.localeScript, sizeof(config.localeScript));
}
@@ -268,10 +268,10 @@
if (script[0]) {
memcpy(out->localeScript, script, sizeof(out->localeScript));
- out->localeScriptWasProvided = true;
+ out->localeScriptWasComputed = false;
} else {
out->computeScript();
- out->localeScriptWasProvided = false;
+ out->localeScriptWasComputed = true;
}
if (variant[0]) {
diff --git a/tools/layoutlib/.idea/libraries/junit.xml b/tools/layoutlib/.idea/libraries/junit.xml
new file mode 100644
index 0000000..c889f5f
--- /dev/null
+++ b/tools/layoutlib/.idea/libraries/junit.xml
@@ -0,0 +1,11 @@
+<component name="libraryTable">
+ <library name="junit">
+ <CLASSES>
+ <root url="jar://$PROJECT_DIR$/../../../../out/host/common/obj/JAVA_LIBRARIES/junit_intermediates/javalib.jar!/" />
+ </CLASSES>
+ <JAVADOC />
+ <SOURCES>
+ <root url="file://$PROJECT_DIR$/../../../../external/junit/src" />
+ </SOURCES>
+ </library>
+</component>
\ No newline at end of file
diff --git a/tools/layoutlib/.idea/runConfigurations/Create.xml b/tools/layoutlib/.idea/runConfigurations/Create.xml
index 58f057a..fb798b6 100644
--- a/tools/layoutlib/.idea/runConfigurations/Create.xml
+++ b/tools/layoutlib/.idea/runConfigurations/Create.xml
@@ -2,7 +2,7 @@
<configuration default="false" name="Create" type="Application" factoryName="Application" singleton="true">
<extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
<option name="MAIN_CLASS_NAME" value="com.android.tools.layoutlib.create.Main" />
- <option name="VM_PARAMETERS" value="" />
+ <option name="VM_PARAMETERS" value="-ea" />
<option name="PROGRAM_PARAMETERS" value="out/host/common/obj/JAVA_LIBRARIES/temp_layoutlib_intermediates/javalib.jar out/target/common/obj/JAVA_LIBRARIES/core-libart_intermediates/classes.jar out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/classes.jar out/target/common/obj/JAVA_LIBRARIES/icu4j-icudata-jarjar_intermediates/classes.jar out/target/common/obj/JAVA_LIBRARIES/icu4j-icutzdata-jarjar_intermediates/classes.jar out/target/common/obj/JAVA_LIBRARIES/ext_intermediates/classes.jar out/target/common/obj/JAVA_LIBRARIES/ext_intermediates/javalib.jar" />
<option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$/../../../../" />
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
diff --git a/tools/layoutlib/Android.mk b/tools/layoutlib/Android.mk
index c2ad9ef..663e1e2 100644
--- a/tools/layoutlib/Android.mk
+++ b/tools/layoutlib/Android.mk
@@ -40,10 +40,8 @@
built_ext_classes := $(call java-lib-files,ext)
built_ext_data := $(call intermediates-dir-for, \
JAVA_LIBRARIES,ext,,COMMON)/javalib.jar
-built_icudata_dep := $(call java-lib-deps,icu4j-icudata-jarjar)
-built_icudata_data := $(call java-lib-files,icu4j-icudata-jarjar)
-built_icutzdata_dep := $(call java-lib-deps,icu4j-icutzdata-jarjar)
-built_icutzdata_data := $(call java-lib-files,icu4j-icutzdata-jarjar)
+built_icudata_dep := $(call java-lib-deps,icu4j-icudata-host-jarjar,HOST)
+built_icutzdata_dep := $(call java-lib-deps,icu4j-icutzdata-host-jarjar,HOST)
built_layoutlib_create_jar := $(call intermediates-dir-for, \
JAVA_LIBRARIES,layoutlib_create,HOST)/javalib.jar
@@ -77,8 +75,8 @@
$(built_core_classes) \
$(built_framework_classes) \
$(built_ext_classes) \
- $(built_icudata_data) \
- $(built_icutzdata_data) \
+ $(built_icudata_dep) \
+ $(built_icutzdata_dep) \
$(built_ext_data)
$(hide) ls -l $(built_framework_classes)
diff --git a/tools/layoutlib/bridge/bridge.iml b/tools/layoutlib/bridge/bridge.iml
index ccc10b3..57d08cb 100644
--- a/tools/layoutlib/bridge/bridge.iml
+++ b/tools/layoutlib/bridge/bridge.iml
@@ -84,6 +84,6 @@
</SOURCES>
</library>
</orderEntry>
- <orderEntry type="library" scope="TEST" name="JUnit4" level="application" />
+ <orderEntry type="library" scope="TEST" name="junit" level="project" />
</component>
</module>
\ No newline at end of file
diff --git a/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java b/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java
index db4c6dc6..ae42ba6 100644
--- a/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java
+++ b/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java
@@ -305,6 +305,12 @@
return defValue;
}
+ @Override
+ public ComplexColor getComplexColor(int index) {
+ // TODO: Support GradientColor
+ return getColorStateList(index);
+ }
+
/**
* Retrieve the ColorStateList for the attribute at <var>index</var>.
* The value may be either a single solid color or a reference to
diff --git a/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java
index c4fbd56..fa880f0 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java
@@ -142,7 +142,7 @@
}
@LayoutlibDelegate
- /*package*/ static void native_setBitmap(long canvas, Bitmap bitmap) {
+ public static void native_setBitmap(long canvas, Bitmap bitmap) {
Canvas_Delegate canvasDelegate = sManager.getDelegate(canvas);
Bitmap_Delegate bitmapDelegate = Bitmap_Delegate.getDelegate(bitmap);
if (canvasDelegate == null || bitmapDelegate==null) {
@@ -153,7 +153,7 @@
}
@LayoutlibDelegate
- /*package*/ static boolean native_isOpaque(long nativeCanvas) {
+ public static boolean native_isOpaque(long nativeCanvas) {
// get the delegate from the native int.
Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
if (canvasDelegate == null) {
@@ -164,10 +164,10 @@
}
@LayoutlibDelegate
- /*package*/ static void native_setHighContrastText(long nativeCanvas, boolean highContrastText){}
+ public static void native_setHighContrastText(long nativeCanvas, boolean highContrastText){}
@LayoutlibDelegate
- /*package*/ static int native_getWidth(long nativeCanvas) {
+ public static int native_getWidth(long nativeCanvas) {
// get the delegate from the native int.
Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
if (canvasDelegate == null) {
@@ -178,7 +178,7 @@
}
@LayoutlibDelegate
- /*package*/ static int native_getHeight(long nativeCanvas) {
+ public static int native_getHeight(long nativeCanvas) {
// get the delegate from the native int.
Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
if (canvasDelegate == null) {
@@ -189,7 +189,7 @@
}
@LayoutlibDelegate
- /*package*/ static int native_save(long nativeCanvas, int saveFlags) {
+ public static int native_save(long nativeCanvas, int saveFlags) {
// get the delegate from the native int.
Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
if (canvasDelegate == null) {
@@ -200,7 +200,7 @@
}
@LayoutlibDelegate
- /*package*/ static int native_saveLayer(long nativeCanvas, float l,
+ public static int native_saveLayer(long nativeCanvas, float l,
float t, float r, float b,
long paint, int layerFlags) {
// get the delegate from the native int.
@@ -219,7 +219,7 @@
}
@LayoutlibDelegate
- /*package*/ static int native_saveLayerAlpha(long nativeCanvas, float l,
+ public static int native_saveLayerAlpha(long nativeCanvas, float l,
float t, float r, float b,
int alpha, int layerFlags) {
// get the delegate from the native int.
@@ -232,7 +232,7 @@
}
@LayoutlibDelegate
- /*package*/ static void native_restore(long nativeCanvas, boolean throwOnUnderflow) {
+ public static void native_restore(long nativeCanvas, boolean throwOnUnderflow) {
// FIXME: implement throwOnUnderflow.
// get the delegate from the native int.
Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
@@ -244,7 +244,7 @@
}
@LayoutlibDelegate
- /*package*/ static void native_restoreToCount(long nativeCanvas, int saveCount,
+ public static void native_restoreToCount(long nativeCanvas, int saveCount,
boolean throwOnUnderflow) {
// FIXME: implement throwOnUnderflow.
// get the delegate from the native int.
@@ -257,7 +257,7 @@
}
@LayoutlibDelegate
- /*package*/ static int native_getSaveCount(long nativeCanvas) {
+ public static int native_getSaveCount(long nativeCanvas) {
// get the delegate from the native int.
Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
if (canvasDelegate == null) {
@@ -268,7 +268,7 @@
}
@LayoutlibDelegate
- /*package*/ static void native_translate(long nativeCanvas, float dx, float dy) {
+ public static void native_translate(long nativeCanvas, float dx, float dy) {
// get the delegate from the native int.
Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
if (canvasDelegate == null) {
@@ -279,7 +279,7 @@
}
@LayoutlibDelegate
- /*package*/ static void native_scale(long nativeCanvas, float sx, float sy) {
+ public static void native_scale(long nativeCanvas, float sx, float sy) {
// get the delegate from the native int.
Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
if (canvasDelegate == null) {
@@ -290,7 +290,7 @@
}
@LayoutlibDelegate
- /*package*/ static void native_rotate(long nativeCanvas, float degrees) {
+ public static void native_rotate(long nativeCanvas, float degrees) {
// get the delegate from the native int.
Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
if (canvasDelegate == null) {
@@ -301,7 +301,7 @@
}
@LayoutlibDelegate
- /*package*/ static void native_skew(long nativeCanvas, float kx, float ky) {
+ public static void native_skew(long nativeCanvas, float kx, float ky) {
// get the delegate from the native int.
Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
if (canvasDelegate == null) {
@@ -325,7 +325,7 @@
}
@LayoutlibDelegate
- /*package*/ static void native_concat(long nCanvas, long nMatrix) {
+ public static void native_concat(long nCanvas, long nMatrix) {
// get the delegate from the native int.
Canvas_Delegate canvasDelegate = sManager.getDelegate(nCanvas);
if (canvasDelegate == null) {
@@ -353,7 +353,7 @@
}
@LayoutlibDelegate
- /*package*/ static void native_setMatrix(long nCanvas, long nMatrix) {
+ public static void native_setMatrix(long nCanvas, long nMatrix) {
// get the delegate from the native int.
Canvas_Delegate canvasDelegate = sManager.getDelegate(nCanvas);
if (canvasDelegate == null) {
@@ -383,7 +383,7 @@
}
@LayoutlibDelegate
- /*package*/ static boolean native_clipRect(long nCanvas,
+ public static boolean native_clipRect(long nCanvas,
float left, float top,
float right, float bottom,
int regionOp) {
@@ -397,7 +397,7 @@
}
@LayoutlibDelegate
- /*package*/ static boolean native_clipPath(long nativeCanvas,
+ public static boolean native_clipPath(long nativeCanvas,
long nativePath,
int regionOp) {
Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
@@ -414,7 +414,7 @@
}
@LayoutlibDelegate
- /*package*/ static boolean native_clipRegion(long nativeCanvas,
+ public static boolean native_clipRegion(long nativeCanvas,
long nativeRegion,
int regionOp) {
Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
@@ -431,7 +431,7 @@
}
@LayoutlibDelegate
- /*package*/ static void nativeSetDrawFilter(long nativeCanvas, long nativeFilter) {
+ public static void nativeSetDrawFilter(long nativeCanvas, long nativeFilter) {
Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
if (canvasDelegate == null) {
return;
@@ -446,7 +446,7 @@
}
@LayoutlibDelegate
- /*package*/ static boolean native_getClipBounds(long nativeCanvas,
+ public static boolean native_getClipBounds(long nativeCanvas,
Rect bounds) {
// get the delegate from the native int.
Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
@@ -467,7 +467,7 @@
}
@LayoutlibDelegate
- /*package*/ static void native_getCTM(long canvas, long matrix) {
+ public static void native_getCTM(long canvas, long matrix) {
// get the delegate from the native int.
Canvas_Delegate canvasDelegate = sManager.getDelegate(canvas);
if (canvasDelegate == null) {
@@ -484,13 +484,13 @@
}
@LayoutlibDelegate
- /*package*/ static boolean native_quickReject(long nativeCanvas, long path) {
+ public static boolean native_quickReject(long nativeCanvas, long path) {
// FIXME properly implement quickReject
return false;
}
@LayoutlibDelegate
- /*package*/ static boolean native_quickReject(long nativeCanvas,
+ public static boolean native_quickReject(long nativeCanvas,
float left, float top,
float right, float bottom) {
// FIXME properly implement quickReject
@@ -498,7 +498,7 @@
}
@LayoutlibDelegate
- /*package*/ static void native_drawColor(long nativeCanvas, final int color, final int mode) {
+ public static void native_drawColor(long nativeCanvas, final int color, final int mode) {
// get the delegate from the native int.
Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
if (canvasDelegate == null) {
@@ -529,14 +529,14 @@
}
@LayoutlibDelegate
- /*package*/ static void native_drawPaint(long nativeCanvas, long paint) {
+ public static void native_drawPaint(long nativeCanvas, long paint) {
// FIXME
Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
"Canvas.drawPaint is not supported.", null, null /*data*/);
}
@LayoutlibDelegate
- /*package*/ static void native_drawPoint(long nativeCanvas, float x, float y,
+ public static void native_drawPoint(long nativeCanvas, float x, float y,
long nativePaint) {
// FIXME
Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
@@ -544,7 +544,7 @@
}
@LayoutlibDelegate
- /*package*/ static void native_drawPoints(long nativeCanvas, float[] pts, int offset, int count,
+ public static void native_drawPoints(long nativeCanvas, float[] pts, int offset, int count,
long nativePaint) {
// FIXME
Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
@@ -552,7 +552,7 @@
}
@LayoutlibDelegate
- /*package*/ static void native_drawLine(long nativeCanvas,
+ public static void native_drawLine(long nativeCanvas,
final float startX, final float startY, final float stopX, final float stopY,
long paint) {
draw(nativeCanvas, paint, false /*compositeOnly*/, false /*forceSrcMode*/,
@@ -565,7 +565,7 @@
}
@LayoutlibDelegate
- /*package*/ static void native_drawLines(long nativeCanvas,
+ public static void native_drawLines(long nativeCanvas,
final float[] pts, final int offset, final int count,
long nativePaint) {
draw(nativeCanvas, nativePaint, false /*compositeOnly*/,
@@ -581,7 +581,7 @@
}
@LayoutlibDelegate
- /*package*/ static void native_drawRect(long nativeCanvas,
+ public static void native_drawRect(long nativeCanvas,
final float left, final float top, final float right, final float bottom, long paint) {
draw(nativeCanvas, paint, false /*compositeOnly*/, false /*forceSrcMode*/,
@@ -607,7 +607,7 @@
}
@LayoutlibDelegate
- /*package*/ static void native_drawOval(long nativeCanvas, final float left,
+ public static void native_drawOval(long nativeCanvas, final float left,
final float top, final float right, final float bottom, long paint) {
if (right > left && bottom > top) {
draw(nativeCanvas, paint, false /*compositeOnly*/, false /*forceSrcMode*/,
@@ -634,7 +634,7 @@
}
@LayoutlibDelegate
- /*package*/ static void native_drawCircle(long nativeCanvas,
+ public static void native_drawCircle(long nativeCanvas,
float cx, float cy, float radius, long paint) {
native_drawOval(nativeCanvas,
cx - radius, cy - radius, cx + radius, cy + radius,
@@ -642,7 +642,7 @@
}
@LayoutlibDelegate
- /*package*/ static void native_drawArc(long nativeCanvas,
+ public static void native_drawArc(long nativeCanvas,
final float left, final float top, final float right, final float bottom,
final float startAngle, final float sweep,
final boolean useCenter, long paint) {
@@ -674,7 +674,7 @@
}
@LayoutlibDelegate
- /*package*/ static void native_drawRoundRect(long nativeCanvas,
+ public static void native_drawRoundRect(long nativeCanvas,
final float left, final float top, final float right, final float bottom,
final float rx, final float ry, long paint) {
draw(nativeCanvas, paint, false /*compositeOnly*/, false /*forceSrcMode*/,
@@ -704,7 +704,7 @@
}
@LayoutlibDelegate
- /*package*/ static void native_drawPath(long nativeCanvas, long path, long paint) {
+ public static void native_drawPath(long nativeCanvas, long path, long paint) {
final Path_Delegate pathDelegate = Path_Delegate.getDelegate(path);
if (pathDelegate == null) {
return;
@@ -756,7 +756,7 @@
}
@LayoutlibDelegate
- /*package*/ static void native_drawRegion(long nativeCanvas, long nativeRegion,
+ public static void native_drawRegion(long nativeCanvas, long nativeRegion,
long nativePaint) {
// FIXME
Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
@@ -764,7 +764,7 @@
}
@LayoutlibDelegate
- /*package*/ static void native_drawNinePatch(Canvas thisCanvas, long nativeCanvas,
+ public static void native_drawNinePatch(Canvas thisCanvas, long nativeCanvas,
long nativeBitmap, long ninePatch, final float dstLeft, final float dstTop,
final float dstRight, final float dstBottom, long nativePaintOrZero,
final int screenDensity, final int bitmapDensity) {
@@ -811,7 +811,7 @@
}
@LayoutlibDelegate
- /*package*/ static void native_drawBitmap(Canvas thisCanvas, long nativeCanvas, Bitmap bitmap,
+ public static void native_drawBitmap(Canvas thisCanvas, long nativeCanvas, Bitmap bitmap,
float left, float top,
long nativePaintOrZero,
int canvasDensity,
@@ -833,7 +833,7 @@
}
@LayoutlibDelegate
- /*package*/ static void native_drawBitmap(Canvas thisCanvas, long nativeCanvas, Bitmap bitmap,
+ public static void native_drawBitmap(Canvas thisCanvas, long nativeCanvas, Bitmap bitmap,
float srcLeft, float srcTop, float srcRight, float srcBottom,
float dstLeft, float dstTop, float dstRight, float dstBottom,
long nativePaintOrZero, int screenDensity, int bitmapDensity) {
@@ -849,7 +849,7 @@
}
@LayoutlibDelegate
- /*package*/ static void native_drawBitmap(long nativeCanvas, int[] colors,
+ public static void native_drawBitmap(long nativeCanvas, int[] colors,
int offset, int stride, final float x,
final float y, int width, int height,
boolean hasAlpha,
@@ -874,7 +874,7 @@
}
@LayoutlibDelegate
- /*package*/ static void nativeDrawBitmapMatrix(long nCanvas, Bitmap bitmap,
+ public static void nativeDrawBitmapMatrix(long nCanvas, Bitmap bitmap,
long nMatrix, long nPaint) {
// get the delegate from the native int.
Canvas_Delegate canvasDelegate = sManager.getDelegate(nCanvas);
@@ -915,7 +915,7 @@
}
@LayoutlibDelegate
- /*package*/ static void nativeDrawBitmapMesh(long nCanvas, Bitmap bitmap,
+ public static void nativeDrawBitmapMesh(long nCanvas, Bitmap bitmap,
int meshWidth, int meshHeight, float[] verts, int vertOffset, int[] colors,
int colorOffset, long nPaint) {
// FIXME
@@ -924,7 +924,7 @@
}
@LayoutlibDelegate
- /*package*/ static void nativeDrawVertices(long nCanvas, int mode, int n,
+ public static void nativeDrawVertices(long nCanvas, int mode, int n,
float[] verts, int vertOffset,
float[] texs, int texOffset,
int[] colors, int colorOffset,
@@ -936,14 +936,14 @@
}
@LayoutlibDelegate
- /*package*/ static void native_drawText(long nativeCanvas, char[] text, int index, int count,
+ public static void native_drawText(long nativeCanvas, char[] text, int index, int count,
float startX, float startY, int flags, long paint, long typeface) {
drawText(nativeCanvas, text, index, count, startX, startY, (flags & 1) != 0,
paint, typeface);
}
@LayoutlibDelegate
- /*package*/ static void native_drawText(long nativeCanvas, String text,
+ public static void native_drawText(long nativeCanvas, String text,
int start, int end, float x, float y, final int flags, long paint,
long typeface) {
int count = end - start;
@@ -954,7 +954,7 @@
}
@LayoutlibDelegate
- /*package*/ static void native_drawTextRun(long nativeCanvas, String text,
+ public static void native_drawTextRun(long nativeCanvas, String text,
int start, int end, int contextStart, int contextEnd,
float x, float y, boolean isRtl, long paint, long typeface) {
int count = end - start;
@@ -965,14 +965,14 @@
}
@LayoutlibDelegate
- /*package*/ static void native_drawTextRun(long nativeCanvas, char[] text,
+ public static void native_drawTextRun(long nativeCanvas, char[] text,
int start, int count, int contextStart, int contextCount,
float x, float y, boolean isRtl, long paint, long typeface) {
drawText(nativeCanvas, text, start, count, x, y, isRtl, paint, typeface);
}
@LayoutlibDelegate
- /*package*/ static void native_drawTextOnPath(long nativeCanvas,
+ public static void native_drawTextOnPath(long nativeCanvas,
char[] text, int index,
int count, long path,
float hOffset,
@@ -984,7 +984,7 @@
}
@LayoutlibDelegate
- /*package*/ static void native_drawTextOnPath(long nativeCanvas,
+ public static void native_drawTextOnPath(long nativeCanvas,
String text, long path,
float hOffset,
float vOffset,
diff --git a/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java
index 514d785..839c182 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java
@@ -223,6 +223,10 @@
return mColorFilter;
}
+ public void setColorFilter(long colorFilterPtr) {
+ mColorFilter = ColorFilter_Delegate.getDelegate(colorFilterPtr);
+ }
+
/**
* Returns the {@link Shader} delegate or null if none have been set
*
diff --git a/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java
index e1da27b..08f0cb4 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java
@@ -572,7 +572,7 @@
return null;
}
- private static void addPath(long destPath, long srcPath, AffineTransform transform) {
+ public static void addPath(long destPath, long srcPath, AffineTransform transform) {
Path_Delegate destPathDelegate = sManager.getDelegate(destPath);
if (destPathDelegate == null) {
return;
@@ -630,7 +630,7 @@
* Fills the given {@link RectF} with the path bounds.
* @param bounds the RectF to be filled.
*/
- private void fillBounds(RectF bounds) {
+ public void fillBounds(RectF bounds) {
Rectangle2D rect = mPath.getBounds2D();
bounds.left = (float)rect.getMinX();
bounds.right = (float)rect.getMaxX();
@@ -644,7 +644,7 @@
* @param x The x-coordinate of the start of a new contour
* @param y The y-coordinate of the start of a new contour
*/
- private void moveTo(float x, float y) {
+ public void moveTo(float x, float y) {
mPath.moveTo(mLastX = x, mLastY = y);
}
@@ -658,7 +658,7 @@
* @param dy The amount to add to the y-coordinate of the end of the
* previous contour, to specify the start of a new contour
*/
- private void rMoveTo(float dx, float dy) {
+ public void rMoveTo(float dx, float dy) {
dx += mLastX;
dy += mLastY;
mPath.moveTo(mLastX = dx, mLastY = dy);
@@ -672,7 +672,7 @@
* @param x The x-coordinate of the end of a line
* @param y The y-coordinate of the end of a line
*/
- private void lineTo(float x, float y) {
+ public void lineTo(float x, float y) {
if (!hasPoints()) {
mPath.moveTo(mLastX = 0, mLastY = 0);
}
@@ -689,7 +689,7 @@
* @param dy The amount to add to the y-coordinate of the previous point on
* this contour, to specify a line
*/
- private void rLineTo(float dx, float dy) {
+ public void rLineTo(float dx, float dy) {
if (!hasPoints()) {
mPath.moveTo(mLastX = 0, mLastY = 0);
}
@@ -714,7 +714,7 @@
* @param x2 The x-coordinate of the end point on a quadratic curve
* @param y2 The y-coordinate of the end point on a quadratic curve
*/
- private void quadTo(float x1, float y1, float x2, float y2) {
+ public void quadTo(float x1, float y1, float x2, float y2) {
mPath.quadTo(x1, y1, mLastX = x2, mLastY = y2);
}
@@ -732,7 +732,7 @@
* @param dy2 The amount to add to the y-coordinate of the last point on
* this contour, for the end point of a quadratic curve
*/
- private void rQuadTo(float dx1, float dy1, float dx2, float dy2) {
+ public void rQuadTo(float dx1, float dy1, float dx2, float dy2) {
if (!hasPoints()) {
mPath.moveTo(mLastX = 0, mLastY = 0);
}
@@ -755,7 +755,7 @@
* @param x3 The x-coordinate of the end point on a cubic curve
* @param y3 The y-coordinate of the end point on a cubic curve
*/
- private void cubicTo(float x1, float y1, float x2, float y2,
+ public void cubicTo(float x1, float y1, float x2, float y2,
float x3, float y3) {
if (!hasPoints()) {
mPath.moveTo(0, 0);
@@ -768,7 +768,7 @@
* current point on this contour. If there is no previous point, then a
* moveTo(0,0) is inserted automatically.
*/
- private void rCubicTo(float dx1, float dy1, float dx2, float dy2,
+ public void rCubicTo(float dx1, float dy1, float dx2, float dy2,
float dx3, float dy3) {
if (!hasPoints()) {
mPath.moveTo(mLastX = 0, mLastY = 0);
@@ -798,7 +798,7 @@
* mod 360.
* @param forceMoveTo If true, always begin a new contour with the arc
*/
- private void arcTo(float left, float top, float right, float bottom, float startAngle,
+ public void arcTo(float left, float top, float right, float bottom, float startAngle,
float sweepAngle,
boolean forceMoveTo) {
Arc2D arc = new Arc2D.Float(left, top, right - left, bottom - top, -startAngle,
@@ -812,7 +812,7 @@
* Close the current contour. If the current point is not equal to the
* first point of the contour, a line segment is automatically added.
*/
- private void close() {
+ public void close() {
mPath.closePath();
}
@@ -831,7 +831,7 @@
* @param bottom The bottom of a rectangle to add to the path
* @param dir The direction to wind the rectangle's contour
*/
- private void addRect(float left, float top, float right, float bottom,
+ public void addRect(float left, float top, float right, float bottom,
int dir) {
moveTo(left, top);
diff --git a/tools/layoutlib/bridge/src/android/graphics/drawable/VectorDrawable_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/drawable/VectorDrawable_Delegate.java
new file mode 100644
index 0000000..eef8235
--- /dev/null
+++ b/tools/layoutlib/bridge/src/android/graphics/drawable/VectorDrawable_Delegate.java
@@ -0,0 +1,1122 @@
+/*
+ * 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.
+ */
+
+package android.graphics.drawable;
+
+import com.android.layoutlib.bridge.impl.DelegateManager;
+import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
+
+import android.content.res.Resources;
+import android.content.res.Resources.Theme;
+import android.content.res.TypedArray;
+import android.graphics.Canvas_Delegate;
+import android.graphics.Color;
+import android.graphics.Matrix;
+import android.graphics.Paint;
+import android.graphics.Paint.Cap;
+import android.graphics.Paint.Join;
+import android.graphics.Paint_Delegate;
+import android.graphics.Path;
+import android.graphics.PathMeasure;
+import android.graphics.Path_Delegate;
+import android.graphics.Rect;
+import android.graphics.Region.Op;
+import android.util.ArrayMap;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.util.MathUtils;
+import android.util.PathParser_Delegate;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.FloatBuffer;
+import java.util.ArrayList;
+
+import static android.graphics.Canvas.CLIP_SAVE_FLAG;
+import static android.graphics.Canvas.MATRIX_SAVE_FLAG;
+import static android.graphics.Paint.Cap.BUTT;
+import static android.graphics.Paint.Cap.ROUND;
+import static android.graphics.Paint.Cap.SQUARE;
+import static android.graphics.Paint.Join.BEVEL;
+import static android.graphics.Paint.Join.MITER;
+import static android.graphics.Paint.Style;
+
+/**
+ * Delegate used to provide new implementation of a select few methods of {@link VectorDrawable}
+ * <p>
+ * Through the layoutlib_create tool, the original methods of VectorDrawable have been replaced by
+ * calls to methods of the same name in this delegate class.
+ */
+@SuppressWarnings("unused")
+public class VectorDrawable_Delegate {
+ private static final String LOGTAG = VectorDrawable_Delegate.class.getSimpleName();
+ private static final boolean DBG_VECTOR_DRAWABLE = false;
+
+ private static final DelegateManager<VNativeObject> sPathManager =
+ new DelegateManager<>(VNativeObject.class);
+
+ private static <T> T getDelegate(long nativePtr) {
+ //noinspection unchecked
+ T object = (T) sPathManager.getDelegate(nativePtr);
+ assert object != null;
+
+ return object;
+ }
+
+ /**
+ * Obtains styled attributes from the theme, if available, or unstyled resources if the theme is
+ * null.
+ */
+ private static TypedArray obtainAttributes(
+ Resources res, Theme theme, AttributeSet set, int[] attrs) {
+ if (theme == null) {
+ return res.obtainAttributes(set, attrs);
+ }
+ return theme.obtainStyledAttributes(set, attrs, 0, 0);
+ }
+
+ private static int applyAlpha(int color, float alpha) {
+ int alphaBytes = Color.alpha(color);
+ color &= 0x00FFFFFF;
+ color |= ((int) (alphaBytes * alpha)) << 24;
+ return color;
+ }
+
+ @LayoutlibDelegate
+ static long nCreateRenderer(long rootGroupPtr) {
+ VGroup_Delegate rootGroup = getDelegate(rootGroupPtr);
+ return sPathManager.addNewDelegate(new VPathRenderer_Delegate(rootGroup));
+ }
+
+ @LayoutlibDelegate
+ static void nSetRendererViewportSize(long rendererPtr, float viewportWidth,
+ float viewportHeight) {
+ VPathRenderer_Delegate nativePathRenderer = getDelegate(rendererPtr);
+ nativePathRenderer.mViewportWidth = viewportWidth;
+ nativePathRenderer.mViewportHeight = viewportHeight;
+ }
+
+ @LayoutlibDelegate
+ static boolean nSetRootAlpha(long rendererPtr, float alpha) {
+ VPathRenderer_Delegate nativePathRenderer = getDelegate(rendererPtr);
+ nativePathRenderer.setRootAlpha(alpha);
+
+ return true;
+ }
+
+ @LayoutlibDelegate
+ static float nGetRootAlpha(long rendererPtr) {
+ VPathRenderer_Delegate nativePathRenderer = getDelegate(rendererPtr);
+
+ return nativePathRenderer.getRootAlpha();
+ }
+
+ @LayoutlibDelegate
+ static void nSetAllowCaching(long rendererPtr, boolean allowCaching) {
+ // ignored
+ }
+
+ @LayoutlibDelegate
+ static void nDraw(long rendererPtr, long canvasWrapperPtr,
+ long colorFilterPtr, Rect bounds, boolean needsMirroring, boolean canReuseCache) {
+ VPathRenderer_Delegate nativePathRenderer =
+ getDelegate(rendererPtr);
+
+ Canvas_Delegate.native_save(canvasWrapperPtr, MATRIX_SAVE_FLAG | CLIP_SAVE_FLAG);
+ Canvas_Delegate.native_translate(canvasWrapperPtr, bounds.left, bounds.top);
+
+ if (needsMirroring) {
+ Canvas_Delegate.native_translate(canvasWrapperPtr, bounds.width(), 0);
+ Canvas_Delegate.native_scale(canvasWrapperPtr, -1.0f, 1.0f);
+ }
+
+ // At this point, canvas has been translated to the right position.
+ // And we use this bound for the destination rect for the drawBitmap, so
+ // we offset to (0, 0);
+ bounds.offsetTo(0, 0);
+ nativePathRenderer.draw(canvasWrapperPtr, colorFilterPtr, bounds.width(), bounds.height());
+
+ Canvas_Delegate.native_restore(canvasWrapperPtr, true);
+ }
+
+ @LayoutlibDelegate
+ static long nCreateFullPath() {
+ return sPathManager.addNewDelegate(new VFullPath_Delegate());
+ }
+
+ @LayoutlibDelegate
+ static long nCreateFullPath(long nativeFullPathPtr) {
+ VFullPath_Delegate original = getDelegate(nativeFullPathPtr);
+
+ return sPathManager.addNewDelegate(new VFullPath_Delegate(original));
+ }
+
+ @LayoutlibDelegate
+ static boolean nGetFullPathProperties(long pathPtr, byte[] propertiesData,
+ int length) {
+ VFullPath_Delegate path = getDelegate(pathPtr);
+
+ ByteBuffer properties = ByteBuffer.wrap(propertiesData);
+ properties.order(ByteOrder.nativeOrder());
+
+ properties.putFloat(VFullPath_Delegate.STROKE_WIDTH_INDEX * 4, path.getStrokeWidth());
+ properties.putInt(VFullPath_Delegate.STROKE_COLOR_INDEX * 4, path.getStrokeColor());
+ properties.putFloat(VFullPath_Delegate.STROKE_ALPHA_INDEX * 4, path.getStrokeAlpha());
+ properties.putInt(VFullPath_Delegate.FILL_COLOR_INDEX * 4, path.getFillColor());
+ properties.putFloat(VFullPath_Delegate.FILL_ALPHA_INDEX * 4, path.getStrokeAlpha());
+ properties.putFloat(VFullPath_Delegate.TRIM_PATH_START_INDEX * 4, path.getTrimPathStart());
+ properties.putFloat(VFullPath_Delegate.TRIM_PATH_END_INDEX * 4, path.getTrimPathEnd());
+ properties.putFloat(VFullPath_Delegate.TRIM_PATH_OFFSET_INDEX * 4,
+ path.getTrimPathOffset());
+ properties.putInt(VFullPath_Delegate.STROKE_LINE_CAP_INDEX * 4, path.getStrokeLineCap());
+ properties.putInt(VFullPath_Delegate.STROKE_LINE_JOIN_INDEX * 4, path.getStrokeLineJoin());
+ properties.putFloat(VFullPath_Delegate.STROKE_MITER_LIMIT_INDEX * 4,
+ path.getStrokeMiterlimit());
+
+ return true;
+ }
+
+ @LayoutlibDelegate
+ static void nUpdateFullPathProperties(long pathPtr, float strokeWidth,
+ int strokeColor, float strokeAlpha, int fillColor, float fillAlpha, float trimPathStart,
+ float trimPathEnd, float trimPathOffset, float strokeMiterLimit, int strokeLineCap,
+ int strokeLineJoin) {
+ VFullPath_Delegate path = getDelegate(pathPtr);
+
+ path.setStrokeWidth(strokeWidth);
+ path.setStrokeColor(strokeColor);
+ path.setStrokeAlpha(strokeAlpha);
+ path.setFillColor(fillColor);
+ path.setFillAlpha(fillAlpha);
+ path.setTrimPathStart(trimPathStart);
+ path.setTrimPathEnd(trimPathEnd);
+ path.setTrimPathOffset(trimPathOffset);
+ path.setStrokeMiterlimit(strokeMiterLimit);
+ path.setStrokeLineCap(strokeLineCap);
+ path.setStrokeLineJoin(strokeLineJoin);
+ }
+
+ @LayoutlibDelegate
+ static void nUpdateFullPathFillGradient(long pathPtr, long fillGradientPtr) {
+
+ }
+
+ @LayoutlibDelegate
+ static void nUpdateFullPathStrokeGradient(long pathPtr, long strokeGradientPtr) {
+
+ }
+
+ @LayoutlibDelegate
+ static long nCreateClipPath() {
+ return sPathManager.addNewDelegate(new VClipPath_Delegate());
+ }
+
+ @LayoutlibDelegate
+ static long nCreateClipPath(long clipPathPtr) {
+ VClipPath_Delegate original = getDelegate(clipPathPtr);
+ return sPathManager.addNewDelegate(new VClipPath_Delegate(original));
+ }
+
+ @LayoutlibDelegate
+ static long nCreateGroup() {
+ return sPathManager.addNewDelegate(new VGroup_Delegate());
+ }
+
+ @LayoutlibDelegate
+ static long nCreateGroup(long groupPtr) {
+ VGroup_Delegate original = getDelegate(groupPtr);
+ return sPathManager.addNewDelegate(
+ new VGroup_Delegate(original, new ArrayMap<String, Object>()));
+ }
+
+ @LayoutlibDelegate
+ static void nSetName(long nodePtr, String name) {
+ VNativeObject group = getDelegate(nodePtr);
+ group.setName(name);
+ }
+
+ @LayoutlibDelegate
+ static boolean nGetGroupProperties(long groupPtr, float[] propertiesData,
+ int length) {
+ VGroup_Delegate group = getDelegate(groupPtr);
+
+ FloatBuffer properties = FloatBuffer.wrap(propertiesData);
+
+ properties.put(VGroup_Delegate.ROTATE_INDEX, group.getRotation());
+ properties.put(VGroup_Delegate.PIVOT_X_INDEX, group.getPivotX());
+ properties.put(VGroup_Delegate.PIVOT_Y_INDEX, group.getPivotY());
+ properties.put(VGroup_Delegate.SCALE_X_INDEX, group.getScaleX());
+ properties.put(VGroup_Delegate.SCALE_Y_INDEX, group.getScaleY());
+ properties.put(VGroup_Delegate.TRANSLATE_X_INDEX, group.getTranslateX());
+ properties.put(VGroup_Delegate.TRANSLATE_Y_INDEX, group.getTranslateY());
+
+ return true;
+ }
+ @LayoutlibDelegate
+ static void nUpdateGroupProperties(long groupPtr, float rotate, float pivotX,
+ float pivotY, float scaleX, float scaleY, float translateX, float translateY) {
+ VGroup_Delegate group = getDelegate(groupPtr);
+
+ group.setRotation(rotate);
+ group.setPivotX(pivotX);
+ group.setPivotY(pivotY);
+ group.setScaleX(scaleX);
+ group.setScaleY(scaleY);
+ group.setTranslateX(translateX);
+ group.setTranslateY(translateY);
+ }
+
+ @LayoutlibDelegate
+ static void nAddChild(long groupPtr, long nodePtr) {
+ VGroup_Delegate group = getDelegate(groupPtr);
+ group.mChildren.add(getDelegate(nodePtr));
+ }
+
+ @LayoutlibDelegate
+ static void nSetPathString(long pathPtr, String pathString, int length) {
+ VPath_Delegate path = getDelegate(pathPtr);
+ path.setPathData(PathParser_Delegate.createNodesFromPathData(pathString));
+ }
+
+ /**
+ * The setters and getters below for paths and groups are here temporarily, and will be removed
+ * once the animation in AVD is replaced with RenderNodeAnimator, in which case the animation
+ * will modify these properties in native. By then no JNI hopping would be necessary for VD
+ * during animation, and these setters and getters will be obsolete.
+ */
+ // Setters and getters during animation.
+ @LayoutlibDelegate
+ static float nGetRotation(long groupPtr) {
+ VGroup_Delegate group = getDelegate(groupPtr);
+ return group.getRotation();
+ }
+
+ @LayoutlibDelegate
+ static void nSetRotation(long groupPtr, float rotation) {
+ VGroup_Delegate group = getDelegate(groupPtr);
+ group.setRotation(rotation);
+ }
+
+ @LayoutlibDelegate
+ static float nGetPivotX(long groupPtr) {
+ VGroup_Delegate group = getDelegate(groupPtr);
+ return group.getPivotX();
+ }
+
+ @LayoutlibDelegate
+ static void nSetPivotX(long groupPtr, float pivotX) {
+ VGroup_Delegate group = getDelegate(groupPtr);
+ group.setPivotX(pivotX);
+ }
+
+ @LayoutlibDelegate
+ static float nGetPivotY(long groupPtr) {
+ VGroup_Delegate group = getDelegate(groupPtr);
+ return group.getPivotY();
+ }
+
+ @LayoutlibDelegate
+ static void nSetPivotY(long groupPtr, float pivotY) {
+ VGroup_Delegate group = getDelegate(groupPtr);
+ group.setPivotY(pivotY);
+ }
+
+ @LayoutlibDelegate
+ static float nGetScaleX(long groupPtr) {
+ VGroup_Delegate group = getDelegate(groupPtr);
+ return group.getScaleX();
+ }
+
+ @LayoutlibDelegate
+ static void nSetScaleX(long groupPtr, float scaleX) {
+ VGroup_Delegate group = getDelegate(groupPtr);
+ group.setScaleX(scaleX);
+ }
+
+ @LayoutlibDelegate
+ static float nGetScaleY(long groupPtr) {
+ VGroup_Delegate group = getDelegate(groupPtr);
+ return group.getScaleY();
+ }
+
+ @LayoutlibDelegate
+ static void nSetScaleY(long groupPtr, float scaleY) {
+ VGroup_Delegate group = getDelegate(groupPtr);
+ group.setScaleY(scaleY);
+ }
+
+ @LayoutlibDelegate
+ static float nGetTranslateX(long groupPtr) {
+ VGroup_Delegate group = getDelegate(groupPtr);
+ return group.getTranslateX();
+ }
+
+ @LayoutlibDelegate
+ static void nSetTranslateX(long groupPtr, float translateX) {
+ VGroup_Delegate group = getDelegate(groupPtr);
+ group.setTranslateX(translateX);
+ }
+
+ @LayoutlibDelegate
+ static float nGetTranslateY(long groupPtr) {
+ VGroup_Delegate group = getDelegate(groupPtr);
+ return group.getTranslateY();
+ }
+
+ @LayoutlibDelegate
+ static void nSetTranslateY(long groupPtr, float translateY) {
+ VGroup_Delegate group = getDelegate(groupPtr);
+ group.setTranslateY(translateY);
+ }
+
+ @LayoutlibDelegate
+ static void nSetPathData(long pathPtr, long pathDataPtr) {
+ VPath_Delegate path = getDelegate(pathPtr);
+ path.setPathData(PathParser_Delegate.getDelegate(pathDataPtr).getPathDataNodes());
+ }
+
+ @LayoutlibDelegate
+ static float nGetStrokeWidth(long pathPtr) {
+ VFullPath_Delegate path = getDelegate(pathPtr);
+ return path.getStrokeWidth();
+ }
+
+ @LayoutlibDelegate
+ static void nSetStrokeWidth(long pathPtr, float width) {
+ VFullPath_Delegate path = getDelegate(pathPtr);
+ path.setStrokeWidth(width);
+ }
+
+ @LayoutlibDelegate
+ static int nGetStrokeColor(long pathPtr) {
+ VFullPath_Delegate path = getDelegate(pathPtr);
+ return path.getStrokeColor();
+ }
+
+ @LayoutlibDelegate
+ static void nSetStrokeColor(long pathPtr, int strokeColor) {
+ VFullPath_Delegate path = getDelegate(pathPtr);
+ path.setStrokeColor(strokeColor);
+ }
+
+ @LayoutlibDelegate
+ static float nGetStrokeAlpha(long pathPtr) {
+ VFullPath_Delegate path = getDelegate(pathPtr);
+ return path.getStrokeAlpha();
+ }
+
+ @LayoutlibDelegate
+ static void nSetStrokeAlpha(long pathPtr, float alpha) {
+ VFullPath_Delegate path = getDelegate(pathPtr);
+ path.setStrokeAlpha(alpha);
+ }
+
+ @LayoutlibDelegate
+ static int nGetFillColor(long pathPtr) {
+ VFullPath_Delegate path = getDelegate(pathPtr);
+ return path.getFillColor();
+ }
+
+ @LayoutlibDelegate
+ static void nSetFillColor(long pathPtr, int fillColor) {
+ VFullPath_Delegate path = getDelegate(pathPtr);
+ path.setFillColor(fillColor);
+ }
+
+ @LayoutlibDelegate
+ static float nGetFillAlpha(long pathPtr) {
+ VFullPath_Delegate path = getDelegate(pathPtr);
+ return path.getFillAlpha();
+ }
+
+ @LayoutlibDelegate
+ static void nSetFillAlpha(long pathPtr, float fillAlpha) {
+ VFullPath_Delegate path = getDelegate(pathPtr);
+ path.setFillAlpha(fillAlpha);
+ }
+
+ @LayoutlibDelegate
+ static float nGetTrimPathStart(long pathPtr) {
+ VFullPath_Delegate path = getDelegate(pathPtr);
+ return path.getTrimPathStart();
+ }
+
+ @LayoutlibDelegate
+ static void nSetTrimPathStart(long pathPtr, float trimPathStart) {
+ VFullPath_Delegate path = getDelegate(pathPtr);
+ path.setTrimPathStart(trimPathStart);
+ }
+
+ @LayoutlibDelegate
+ static float nGetTrimPathEnd(long pathPtr) {
+ VFullPath_Delegate path = getDelegate(pathPtr);
+ return path.getTrimPathEnd();
+ }
+
+ @LayoutlibDelegate
+ static void nSetTrimPathEnd(long pathPtr, float trimPathEnd) {
+ VFullPath_Delegate path = getDelegate(pathPtr);
+ path.setTrimPathEnd(trimPathEnd);
+ }
+
+ @LayoutlibDelegate
+ static float nGetTrimPathOffset(long pathPtr) {
+ VFullPath_Delegate path = getDelegate(pathPtr);
+ return path.getTrimPathOffset();
+ }
+
+ @LayoutlibDelegate
+ static void nSetTrimPathOffset(long pathPtr, float trimPathOffset) {
+ VFullPath_Delegate path = getDelegate(pathPtr);
+ path.setTrimPathOffset(trimPathOffset);
+ }
+
+ /**
+ * Base class for all the internal Delegates that does two functions:
+ * <ol>
+ * <li>Serves as base class to store all the delegates in one {@link DelegateManager}
+ * <li>Provides setName for all the classes. {@link VPathRenderer_Delegate} does actually
+ * not need it
+ * </ol>
+ */
+ private interface VNativeObject {
+ void setName(String name);
+ }
+
+ private static class VClipPath_Delegate extends VPath_Delegate {
+ private VClipPath_Delegate() {
+ // Empty constructor.
+ }
+
+ private VClipPath_Delegate(VClipPath_Delegate copy) {
+ super(copy);
+ }
+
+ @Override
+ public boolean isClipPath() {
+ return true;
+ }
+ }
+
+ private static class VFullPath_Delegate extends VPath_Delegate {
+ // These constants need to be kept in sync with their values in VectorDrawable.VFullPath
+ private static final int STROKE_WIDTH_INDEX = 0;
+ private static final int STROKE_COLOR_INDEX = 1;
+ private static final int STROKE_ALPHA_INDEX = 2;
+ private static final int FILL_COLOR_INDEX = 3;
+ private static final int FILL_ALPHA_INDEX = 4;
+ private static final int TRIM_PATH_START_INDEX = 5;
+ private static final int TRIM_PATH_END_INDEX = 6;
+ private static final int TRIM_PATH_OFFSET_INDEX = 7;
+ private static final int STROKE_LINE_CAP_INDEX = 8;
+ private static final int STROKE_LINE_JOIN_INDEX = 9;
+ private static final int STROKE_MITER_LIMIT_INDEX = 10;
+
+ private static final int LINECAP_BUTT = 0;
+ private static final int LINECAP_ROUND = 1;
+ private static final int LINECAP_SQUARE = 2;
+
+ private static final int LINEJOIN_MITER = 0;
+ private static final int LINEJOIN_ROUND = 1;
+ private static final int LINEJOIN_BEVEL = 2;
+
+ /////////////////////////////////////////////////////
+ // Variables below need to be copied (deep copy if applicable) for mutation.
+
+ int mStrokeColor = Color.TRANSPARENT;
+ float mStrokeWidth = 0;
+
+ int mFillColor = Color.TRANSPARENT;
+ float mStrokeAlpha = 1.0f;
+ float mFillAlpha = 1.0f;
+ float mTrimPathStart = 0;
+ float mTrimPathEnd = 1;
+ float mTrimPathOffset = 0;
+
+ Cap mStrokeLineCap = BUTT;
+ Join mStrokeLineJoin = MITER;
+ float mStrokeMiterlimit = 4;
+
+ private VFullPath_Delegate() {
+ // Empty constructor.
+ }
+
+ private VFullPath_Delegate(VFullPath_Delegate copy) {
+ super(copy);
+
+ mStrokeColor = copy.mStrokeColor;
+ mStrokeWidth = copy.mStrokeWidth;
+ mStrokeAlpha = copy.mStrokeAlpha;
+ mFillColor = copy.mFillColor;
+ mFillAlpha = copy.mFillAlpha;
+ mTrimPathStart = copy.mTrimPathStart;
+ mTrimPathEnd = copy.mTrimPathEnd;
+ mTrimPathOffset = copy.mTrimPathOffset;
+
+ mStrokeLineCap = copy.mStrokeLineCap;
+ mStrokeLineJoin = copy.mStrokeLineJoin;
+ mStrokeMiterlimit = copy.mStrokeMiterlimit;
+ }
+
+ private int getStrokeLineCap() {
+ switch (mStrokeLineCap) {
+ case BUTT:
+ return LINECAP_BUTT;
+ case ROUND:
+ return LINECAP_ROUND;
+ case SQUARE:
+ return LINECAP_SQUARE;
+ default:
+ assert false;
+ }
+
+ return -1;
+ }
+
+ private void setStrokeLineCap(int cap) {
+ switch (cap) {
+ case LINECAP_BUTT:
+ mStrokeLineCap = BUTT;
+ break;
+ case LINECAP_ROUND:
+ mStrokeLineCap = ROUND;
+ break;
+ case LINECAP_SQUARE:
+ mStrokeLineCap = SQUARE;
+ break;
+ default:
+ assert false;
+ }
+ }
+
+ private int getStrokeLineJoin() {
+ switch (mStrokeLineJoin) {
+ case MITER:
+ return LINEJOIN_MITER;
+ case ROUND:
+ return LINEJOIN_ROUND;
+ case BEVEL:
+ return LINEJOIN_BEVEL;
+ default:
+ assert false;
+ }
+
+ return -1;
+ }
+
+ private void setStrokeLineJoin(int join) {
+ switch (join) {
+ case LINEJOIN_BEVEL:
+ mStrokeLineJoin = BEVEL;
+ break;
+ case LINEJOIN_MITER:
+ mStrokeLineJoin = MITER;
+ break;
+ case LINEJOIN_ROUND:
+ mStrokeLineJoin = Join.ROUND;
+ break;
+ default:
+ assert false;
+ }
+ }
+
+ private int getStrokeColor() {
+ return mStrokeColor;
+ }
+
+ private void setStrokeColor(int strokeColor) {
+ mStrokeColor = strokeColor;
+ }
+
+ private float getStrokeWidth() {
+ return mStrokeWidth;
+ }
+
+ private void setStrokeWidth(float strokeWidth) {
+ mStrokeWidth = strokeWidth;
+ }
+
+ private float getStrokeAlpha() {
+ return mStrokeAlpha;
+ }
+
+ private void setStrokeAlpha(float strokeAlpha) {
+ mStrokeAlpha = strokeAlpha;
+ }
+
+ private int getFillColor() {
+ return mFillColor;
+ }
+
+ private void setFillColor(int fillColor) {
+ mFillColor = fillColor;
+ }
+
+ private float getFillAlpha() {
+ return mFillAlpha;
+ }
+
+ private void setFillAlpha(float fillAlpha) {
+ mFillAlpha = fillAlpha;
+ }
+
+ private float getTrimPathStart() {
+ return mTrimPathStart;
+ }
+
+ private void setTrimPathStart(float trimPathStart) {
+ mTrimPathStart = trimPathStart;
+ }
+
+ private float getTrimPathEnd() {
+ return mTrimPathEnd;
+ }
+
+ private void setTrimPathEnd(float trimPathEnd) {
+ mTrimPathEnd = trimPathEnd;
+ }
+
+ private float getTrimPathOffset() {
+ return mTrimPathOffset;
+ }
+
+ private void setTrimPathOffset(float trimPathOffset) {
+ mTrimPathOffset = trimPathOffset;
+ }
+
+ private void setStrokeMiterlimit(float limit) {
+ mStrokeMiterlimit = limit;
+ }
+
+ private float getStrokeMiterlimit() {
+ return mStrokeMiterlimit;
+ }
+ }
+
+ private static class VGroup_Delegate implements VNativeObject {
+ // This constants need to be kept in sync with their definitions in VectorDrawable.Group
+ private static final int ROTATE_INDEX = 0;
+ private static final int PIVOT_X_INDEX = 1;
+ private static final int PIVOT_Y_INDEX = 2;
+ private static final int SCALE_X_INDEX = 3;
+ private static final int SCALE_Y_INDEX = 4;
+ private static final int TRANSLATE_X_INDEX = 5;
+ private static final int TRANSLATE_Y_INDEX = 6;
+
+ /////////////////////////////////////////////////////
+ // Variables below need to be copied (deep copy if applicable) for mutation.
+ final ArrayList<Object> mChildren = new ArrayList<>();
+ // mStackedMatrix is only used temporarily when drawing, it combines all
+ // the parents' local matrices with the current one.
+ private final Matrix mStackedMatrix = new Matrix();
+ // mLocalMatrix is updated based on the update of transformation information,
+ // either parsed from the XML or by animation.
+ private final Matrix mLocalMatrix = new Matrix();
+ private float mRotate = 0;
+ private float mPivotX = 0;
+ private float mPivotY = 0;
+ private float mScaleX = 1;
+ private float mScaleY = 1;
+ private float mTranslateX = 0;
+ private float mTranslateY = 0;
+ private int mChangingConfigurations;
+ private String mGroupName = null;
+
+ private VGroup_Delegate(VGroup_Delegate copy, ArrayMap<String, Object> targetsMap) {
+ mRotate = copy.mRotate;
+ mPivotX = copy.mPivotX;
+ mPivotY = copy.mPivotY;
+ mScaleX = copy.mScaleX;
+ mScaleY = copy.mScaleY;
+ mTranslateX = copy.mTranslateX;
+ mTranslateY = copy.mTranslateY;
+ mGroupName = copy.mGroupName;
+ mChangingConfigurations = copy.mChangingConfigurations;
+ if (mGroupName != null) {
+ targetsMap.put(mGroupName, this);
+ }
+
+ mLocalMatrix.set(copy.mLocalMatrix);
+
+ final ArrayList<Object> children = copy.mChildren;
+ //noinspection ForLoopReplaceableByForEach
+ for (int i = 0; i < children.size(); i++) {
+ Object copyChild = children.get(i);
+ if (copyChild instanceof VGroup_Delegate) {
+ VGroup_Delegate copyGroup = (VGroup_Delegate) copyChild;
+ mChildren.add(new VGroup_Delegate(copyGroup, targetsMap));
+ } else {
+ VPath_Delegate newPath;
+ if (copyChild instanceof VFullPath_Delegate) {
+ newPath = new VFullPath_Delegate((VFullPath_Delegate) copyChild);
+ } else if (copyChild instanceof VClipPath_Delegate) {
+ newPath = new VClipPath_Delegate((VClipPath_Delegate) copyChild);
+ } else {
+ throw new IllegalStateException("Unknown object in the tree!");
+ }
+ mChildren.add(newPath);
+ if (newPath.mPathName != null) {
+ targetsMap.put(newPath.mPathName, newPath);
+ }
+ }
+ }
+ }
+
+ private VGroup_Delegate() {
+ }
+
+ private void updateLocalMatrix() {
+ // The order we apply is the same as the
+ // RenderNode.cpp::applyViewPropertyTransforms().
+ mLocalMatrix.reset();
+ mLocalMatrix.postTranslate(-mPivotX, -mPivotY);
+ mLocalMatrix.postScale(mScaleX, mScaleY);
+ mLocalMatrix.postRotate(mRotate, 0, 0);
+ mLocalMatrix.postTranslate(mTranslateX + mPivotX, mTranslateY + mPivotY);
+ }
+
+ /* Setters and Getters, used by animator from AnimatedVectorDrawable. */
+ private float getRotation() {
+ return mRotate;
+ }
+
+ private void setRotation(float rotation) {
+ if (rotation != mRotate) {
+ mRotate = rotation;
+ updateLocalMatrix();
+ }
+ }
+
+ private float getPivotX() {
+ return mPivotX;
+ }
+
+ private void setPivotX(float pivotX) {
+ if (pivotX != mPivotX) {
+ mPivotX = pivotX;
+ updateLocalMatrix();
+ }
+ }
+
+ private float getPivotY() {
+ return mPivotY;
+ }
+
+ private void setPivotY(float pivotY) {
+ if (pivotY != mPivotY) {
+ mPivotY = pivotY;
+ updateLocalMatrix();
+ }
+ }
+
+ private float getScaleX() {
+ return mScaleX;
+ }
+
+ private void setScaleX(float scaleX) {
+ if (scaleX != mScaleX) {
+ mScaleX = scaleX;
+ updateLocalMatrix();
+ }
+ }
+
+ private float getScaleY() {
+ return mScaleY;
+ }
+
+ private void setScaleY(float scaleY) {
+ if (scaleY != mScaleY) {
+ mScaleY = scaleY;
+ updateLocalMatrix();
+ }
+ }
+
+ private float getTranslateX() {
+ return mTranslateX;
+ }
+
+ private void setTranslateX(float translateX) {
+ if (translateX != mTranslateX) {
+ mTranslateX = translateX;
+ updateLocalMatrix();
+ }
+ }
+
+ private float getTranslateY() {
+ return mTranslateY;
+ }
+
+ private void setTranslateY(float translateY) {
+ if (translateY != mTranslateY) {
+ mTranslateY = translateY;
+ updateLocalMatrix();
+ }
+ }
+
+ @Override
+ public void setName(String name) {
+ mGroupName = name;
+ }
+ }
+
+ public static class VPath_Delegate implements VNativeObject {
+ protected PathParser_Delegate.PathDataNode[] mNodes = null;
+ String mPathName;
+ int mChangingConfigurations;
+
+ public VPath_Delegate() {
+ // Empty constructor.
+ }
+
+ public VPath_Delegate(VPath_Delegate copy) {
+ mPathName = copy.mPathName;
+ mChangingConfigurations = copy.mChangingConfigurations;
+ mNodes = PathParser_Delegate.deepCopyNodes(copy.mNodes);
+ }
+
+ public void toPath(Path path) {
+ path.reset();
+ if (mNodes != null) {
+ PathParser_Delegate.PathDataNode.nodesToPath(mNodes,
+ Path_Delegate.getDelegate(path.mNativePath));
+ }
+ }
+
+ @Override
+ public void setName(String name) {
+ mPathName = name;
+ }
+
+ public boolean isClipPath() {
+ return false;
+ }
+
+ private void setPathData(PathParser_Delegate.PathDataNode[] nodes) {
+ if (!PathParser_Delegate.canMorph(mNodes, nodes)) {
+ // This should not happen in the middle of animation.
+ mNodes = PathParser_Delegate.deepCopyNodes(nodes);
+ } else {
+ PathParser_Delegate.updateNodes(mNodes, nodes);
+ }
+ }
+ }
+
+ private static class VPathRenderer_Delegate implements VNativeObject {
+ /* Right now the internal data structure is organized as a tree.
+ * Each node can be a group node, or a path.
+ * A group node can have groups or paths as children, but a path node has
+ * no children.
+ * One example can be:
+ * Root Group
+ * / | \
+ * Group Path Group
+ * / \ |
+ * Path Path Path
+ *
+ */
+ // Variables that only used temporarily inside the draw() call, so there
+ // is no need for deep copying.
+ private final Path mPath;
+ private final Path mRenderPath;
+ private final Matrix mFinalPathMatrix = new Matrix();
+ private final VGroup_Delegate mRootGroup;
+ private float mViewportWidth = 0;
+ private float mViewportHeight = 0;
+ private float mRootAlpha = 1.0f;
+ private Paint mStrokePaint;
+ private Paint mFillPaint;
+ private PathMeasure mPathMeasure;
+
+ private VPathRenderer_Delegate(VGroup_Delegate rootGroup) {
+ mRootGroup = rootGroup;
+ mPath = new Path();
+ mRenderPath = new Path();
+ }
+
+ private float getRootAlpha() {
+ return mRootAlpha;
+ }
+
+ private void setRootAlpha(float alpha) {
+ mRootAlpha = alpha;
+ }
+
+ private void drawGroupTree(VGroup_Delegate currentGroup, Matrix currentMatrix,
+ long canvasPtr, int w, int h, long filterPtr) {
+ // Calculate current group's matrix by preConcat the parent's and
+ // and the current one on the top of the stack.
+ // Basically the Mfinal = Mviewport * M0 * M1 * M2;
+ // Mi the local matrix at level i of the group tree.
+ currentGroup.mStackedMatrix.set(currentMatrix);
+ currentGroup.mStackedMatrix.preConcat(currentGroup.mLocalMatrix);
+
+ // Save the current clip information, which is local to this group.
+ Canvas_Delegate.native_save(canvasPtr, MATRIX_SAVE_FLAG | CLIP_SAVE_FLAG);
+ // Draw the group tree in the same order as the XML file.
+ for (int i = 0; i < currentGroup.mChildren.size(); i++) {
+ Object child = currentGroup.mChildren.get(i);
+ if (child instanceof VGroup_Delegate) {
+ VGroup_Delegate childGroup = (VGroup_Delegate) child;
+ drawGroupTree(childGroup, currentGroup.mStackedMatrix,
+ canvasPtr, w, h, filterPtr);
+ } else if (child instanceof VPath_Delegate) {
+ VPath_Delegate childPath = (VPath_Delegate) child;
+ drawPath(currentGroup, childPath, canvasPtr, w, h, filterPtr);
+ }
+ }
+ Canvas_Delegate.native_restore(canvasPtr, true);
+ }
+
+ public void draw(long canvasPtr, long filterPtr, int w, int h) {
+ // Traverse the tree in pre-order to draw.
+ drawGroupTree(mRootGroup, Matrix.IDENTITY_MATRIX, canvasPtr, w, h, filterPtr);
+ }
+
+ private void drawPath(VGroup_Delegate VGroup, VPath_Delegate VPath, long canvasPtr,
+ int w,
+ int h,
+ long filterPtr) {
+ final float scaleX = w / mViewportWidth;
+ final float scaleY = h / mViewportHeight;
+ final float minScale = Math.min(scaleX, scaleY);
+ final Matrix groupStackedMatrix = VGroup.mStackedMatrix;
+
+ mFinalPathMatrix.set(groupStackedMatrix);
+ mFinalPathMatrix.postScale(scaleX, scaleY);
+
+ final float matrixScale = getMatrixScale(groupStackedMatrix);
+ if (matrixScale == 0) {
+ // When either x or y is scaled to 0, we don't need to draw anything.
+ return;
+ }
+ VPath.toPath(mPath);
+ final Path path = mPath;
+
+ mRenderPath.reset();
+
+ if (VPath.isClipPath()) {
+ mRenderPath.addPath(path, mFinalPathMatrix);
+ Canvas_Delegate.native_clipPath(canvasPtr, mRenderPath.mNativePath, Op
+ .INTERSECT.nativeInt);
+ } else {
+ VFullPath_Delegate fullPath = (VFullPath_Delegate) VPath;
+ if (fullPath.mTrimPathStart != 0.0f || fullPath.mTrimPathEnd != 1.0f) {
+ float start = (fullPath.mTrimPathStart + fullPath.mTrimPathOffset) % 1.0f;
+ float end = (fullPath.mTrimPathEnd + fullPath.mTrimPathOffset) % 1.0f;
+
+ if (mPathMeasure == null) {
+ mPathMeasure = new PathMeasure();
+ }
+ mPathMeasure.setPath(mPath, false);
+
+ float len = mPathMeasure.getLength();
+ start = start * len;
+ end = end * len;
+ path.reset();
+ if (start > end) {
+ mPathMeasure.getSegment(start, len, path, true);
+ mPathMeasure.getSegment(0f, end, path, true);
+ } else {
+ mPathMeasure.getSegment(start, end, path, true);
+ }
+ path.rLineTo(0, 0); // fix bug in measure
+ }
+ mRenderPath.addPath(path, mFinalPathMatrix);
+
+ if (fullPath.mFillColor != Color.TRANSPARENT) {
+ if (mFillPaint == null) {
+ mFillPaint = new Paint();
+ mFillPaint.setStyle(Style.FILL);
+ mFillPaint.setAntiAlias(true);
+ }
+
+ final Paint fillPaint = mFillPaint;
+ fillPaint.setColor(applyAlpha(fullPath.mFillColor, fullPath.mFillAlpha));
+ Paint_Delegate fillPaintDelegate = Paint_Delegate.getDelegate(fillPaint
+ .getNativeInstance
+ ());
+ // mFillPaint can not be null at this point so we will have a delegate
+ assert fillPaintDelegate != null;
+ fillPaintDelegate.setColorFilter(filterPtr);
+ Canvas_Delegate.native_drawPath(canvasPtr, mRenderPath.mNativePath, fillPaint
+ .getNativeInstance());
+ }
+
+ if (fullPath.mStrokeColor != Color.TRANSPARENT) {
+ if (mStrokePaint == null) {
+ mStrokePaint = new Paint();
+ mStrokePaint.setStyle(Style.STROKE);
+ mStrokePaint.setAntiAlias(true);
+ }
+
+ final Paint strokePaint = mStrokePaint;
+ if (fullPath.mStrokeLineJoin != null) {
+ strokePaint.setStrokeJoin(fullPath.mStrokeLineJoin);
+ }
+
+ if (fullPath.mStrokeLineCap != null) {
+ strokePaint.setStrokeCap(fullPath.mStrokeLineCap);
+ }
+
+ strokePaint.setStrokeMiter(fullPath.mStrokeMiterlimit);
+ strokePaint.setColor(applyAlpha(fullPath.mStrokeColor, fullPath.mStrokeAlpha));
+ Paint_Delegate strokePaintDelegate = Paint_Delegate.getDelegate(strokePaint
+ .getNativeInstance());
+ // mStrokePaint can not be null at this point so we will have a delegate
+ assert strokePaintDelegate != null;
+ strokePaintDelegate.setColorFilter(filterPtr);
+ final float finalStrokeScale = minScale * matrixScale;
+ strokePaint.setStrokeWidth(fullPath.mStrokeWidth * finalStrokeScale);
+ Canvas_Delegate.native_drawPath(canvasPtr, mRenderPath.mNativePath, strokePaint
+ .getNativeInstance());
+ }
+ }
+ }
+
+ private float getMatrixScale(Matrix groupStackedMatrix) {
+ // Given unit vectors A = (0, 1) and B = (1, 0).
+ // After matrix mapping, we got A' and B'. Let theta = the angel b/t A' and B'.
+ // Therefore, the final scale we want is min(|A'| * sin(theta), |B'| * sin(theta)),
+ // which is (|A'| * |B'| * sin(theta)) / max (|A'|, |B'|);
+ // If max (|A'|, |B'|) = 0, that means either x or y has a scale of 0.
+ //
+ // For non-skew case, which is most of the cases, matrix scale is computing exactly the
+ // scale on x and y axis, and take the minimal of these two.
+ // For skew case, an unit square will mapped to a parallelogram. And this function will
+ // return the minimal height of the 2 bases.
+ float[] unitVectors = new float[]{0, 1, 1, 0};
+ groupStackedMatrix.mapVectors(unitVectors);
+ float scaleX = MathUtils.mag(unitVectors[0], unitVectors[1]);
+ float scaleY = MathUtils.mag(unitVectors[2], unitVectors[3]);
+ float crossProduct = MathUtils.cross(unitVectors[0], unitVectors[1],
+ unitVectors[2], unitVectors[3]);
+ float maxScale = MathUtils.max(scaleX, scaleY);
+
+ float matrixScale = 0;
+ if (maxScale > 0) {
+ matrixScale = MathUtils.abs(crossProduct) / maxScale;
+ }
+ if (DBG_VECTOR_DRAWABLE) {
+ Log.d(LOGTAG, "Scale x " + scaleX + " y " + scaleY + " final " + matrixScale);
+ }
+ return matrixScale;
+ }
+
+ @Override
+ public void setName(String name) {
+ }
+ }
+}
diff --git a/tools/layoutlib/bridge/src/android/util/PathParser_Delegate.java b/tools/layoutlib/bridge/src/android/util/PathParser_Delegate.java
index d3af837..6c34c70 100644
--- a/tools/layoutlib/bridge/src/android/util/PathParser_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/util/PathParser_Delegate.java
@@ -24,7 +24,6 @@
import android.annotation.NonNull;
import android.graphics.Path_Delegate;
-import java.awt.geom.Path2D;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.logging.Level;
@@ -52,10 +51,18 @@
@NonNull
private PathDataNode[] mPathDataNodes;
+ public static PathParser_Delegate getDelegate(long nativePtr) {
+ return sManager.getDelegate(nativePtr);
+ }
+
private PathParser_Delegate(@NonNull PathDataNode[] nodes) {
mPathDataNodes = nodes;
}
+ public PathDataNode[] getPathDataNodes() {
+ return mPathDataNodes;
+ }
+
@LayoutlibDelegate
/*package*/ static boolean nParseStringForPath(long pathPtr, @NonNull String pathString, int
stringLength) {
@@ -64,7 +71,7 @@
return false;
}
assert pathString.length() == stringLength;
- PathDataNode.nodesToPath(createNodesFromPathData(pathString), path_delegate.getJavaShape());
+ PathDataNode.nodesToPath(createNodesFromPathData(pathString), path_delegate);
return true;
}
@@ -75,7 +82,7 @@
if (source == null || path_delegate == null) {
return;
}
- PathDataNode.nodesToPath(source.mPathDataNodes, path_delegate.getJavaShape());
+ PathDataNode.nodesToPath(source.mPathDataNodes, path_delegate);
}
@LayoutlibDelegate
@@ -124,8 +131,11 @@
out.mPathDataNodes = new PathDataNode[length];
}
for (int i = 0; i < length; i++) {
+ if (out.mPathDataNodes[i] == null) {
+ out.mPathDataNodes[i] = new PathDataNode(from.mPathDataNodes[i]);
+ }
out.mPathDataNodes[i].interpolatePathDataNode(from.mPathDataNodes[i],
- to.mPathDataNodes[i], fraction);
+ to.mPathDataNodes[i], fraction);
}
return true;
}
@@ -137,9 +147,13 @@
@LayoutlibDelegate
/*package*/ static boolean nCanMorph(long fromDataPtr, long toDataPtr) {
- Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED, "morphing path data isn't " +
- "supported", null, null);
- return false;
+ PathParser_Delegate fromPath = PathParser_Delegate.getDelegate(fromDataPtr);
+ PathParser_Delegate toPath = PathParser_Delegate.getDelegate(toDataPtr);
+ if (fromPath == null || toPath == null || fromPath.getPathDataNodes() == null || toPath
+ .getPathDataNodes() == null) {
+ return true;
+ }
+ return PathParser_Delegate.canMorph(fromPath.getPathDataNodes(), toPath.getPathDataNodes());
}
@LayoutlibDelegate
@@ -158,7 +172,7 @@
* @return an array of the PathDataNode.
*/
@NonNull
- private static PathDataNode[] createNodesFromPathData(@NonNull String pathData) {
+ public static PathDataNode[] createNodesFromPathData(@NonNull String pathData) {
int start = 0;
int end = 1;
@@ -186,7 +200,7 @@
* @return a deep copy of the <code>source</code>.
*/
@NonNull
- private static PathDataNode[] deepCopyNodes(@NonNull PathDataNode[] source) {
+ public static PathDataNode[] deepCopyNodes(@NonNull PathDataNode[] source) {
PathDataNode[] copy = new PathDataNode[source.length];
for (int i = 0; i < source.length; i++) {
copy[i] = new PathDataNode(source[i]);
@@ -194,6 +208,45 @@
return copy;
}
+ /**
+ * @param nodesFrom The source path represented in an array of PathDataNode
+ * @param nodesTo The target path represented in an array of PathDataNode
+ * @return whether the <code>nodesFrom</code> can morph into <code>nodesTo</code>
+ */
+ public static boolean canMorph(PathDataNode[] nodesFrom, PathDataNode[] nodesTo) {
+ if (nodesFrom == null || nodesTo == null) {
+ return false;
+ }
+
+ if (nodesFrom.length != nodesTo.length) {
+ return false;
+ }
+
+ for (int i = 0; i < nodesFrom.length; i ++) {
+ if (nodesFrom[i].mType != nodesTo[i].mType
+ || nodesFrom[i].mParams.length != nodesTo[i].mParams.length) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Update the target's data to match the source.
+ * Before calling this, make sure canMorph(target, source) is true.
+ *
+ * @param target The target path represented in an array of PathDataNode
+ * @param source The source path represented in an array of PathDataNode
+ */
+ public static void updateNodes(PathDataNode[] target, PathDataNode[] source) {
+ for (int i = 0; i < source.length; i ++) {
+ target[i].mType = source[i].mType;
+ for (int j = 0; j < source[i].mParams.length; j ++) {
+ target[i].mParams[j] = source[i].mParams[j];
+ }
+ }
+ }
+
private static int nextStart(@NonNull String s, int end) {
char c;
@@ -330,7 +383,7 @@
* Each PathDataNode represents one command in the "d" attribute of the svg file. An array of
* PathDataNode can represent the whole "d" attribute.
*/
- private static class PathDataNode {
+ public static class PathDataNode {
private char mType;
@NonNull
private float[] mParams;
@@ -355,12 +408,13 @@
}
/**
- * Convert an array of PathDataNode to Path.
+ * Convert an array of PathDataNode to Path. Reset the passed path as needed before
+ * calling this method.
*
* @param node The source array of PathDataNode.
* @param path The target Path object.
*/
- private static void nodesToPath(@NonNull PathDataNode[] node, @NonNull Path2D path) {
+ public static void nodesToPath(@NonNull PathDataNode[] node, @NonNull Path_Delegate path) {
float[] current = new float[6];
char previousCommand = 'm';
//noinspection ForLoopReplaceableByForEach
@@ -387,24 +441,32 @@
}
@SuppressWarnings("PointlessArithmeticExpression")
- private static void addCommand(@NonNull Path2D path, float[] current, char cmd,
- char lastCmd, @NonNull float[] val) {
+ private static void addCommand(@NonNull Path_Delegate path, float[] current,
+ char previousCmd, char cmd, @NonNull float[] val) {
int incr = 2;
-
- float cx = current[0];
- float cy = current[1];
- float cpx = current[2];
- float cpy = current[3];
- float loopX = current[4];
- float loopY = current[5];
+ float currentX = current[0];
+ float currentY = current[1];
+ float ctrlPointX = current[2];
+ float ctrlPointY = current[3];
+ float currentSegmentStartX = current[4];
+ float currentSegmentStartY = current[5];
+ float reflectiveCtrlPointX;
+ float reflectiveCtrlPointY;
switch (cmd) {
case 'z':
case 'Z':
- path.closePath();
- cx = loopX;
- cy = loopY;
+ path.close();
+ // Path is closed here, but we need to move the pen to the
+ // closed position. So we cache the segment's starting position,
+ // and restore it here.
+ currentX = currentSegmentStartX;
+ currentY = currentSegmentStartY;
+ ctrlPointX = currentSegmentStartX;
+ ctrlPointY = currentSegmentStartY;
+ path.moveTo(currentX, currentY);
+ break;
case 'm':
case 'M':
case 'l':
@@ -432,185 +494,206 @@
case 'a':
case 'A':
incr = 7;
+ break;
}
for (int k = 0; k < val.length; k += incr) {
- boolean reflectCtrl;
- float tempReflectedX, tempReflectedY;
-
switch (cmd) {
- case 'm':
- cx += val[k + 0];
- cy += val[k + 1];
+ case 'm': // moveto - Start a new sub-path (relative)
+ currentX += val[k + 0];
+ currentY += val[k + 1];
+
if (k > 0) {
// According to the spec, if a moveto is followed by multiple
// pairs of coordinates, the subsequent pairs are treated as
// implicit lineto commands.
- path.lineTo(cx, cy);
+ path.rLineTo(val[k + 0], val[k + 1]);
} else {
- path.moveTo(cx, cy);
- loopX = cx;
- loopY = cy;
+ path.rMoveTo(val[k + 0], val[k + 1]);
+ currentSegmentStartX = currentX;
+ currentSegmentStartY = currentY;
}
break;
- case 'M':
- cx = val[k + 0];
- cy = val[k + 1];
+ case 'M': // moveto - Start a new sub-path
+ currentX = val[k + 0];
+ currentY = val[k + 1];
+
if (k > 0) {
// According to the spec, if a moveto is followed by multiple
// pairs of coordinates, the subsequent pairs are treated as
// implicit lineto commands.
- path.lineTo(cx, cy);
+ path.lineTo(val[k + 0], val[k + 1]);
} else {
- path.moveTo(cx, cy);
- loopX = cx;
- loopY = cy;
+ path.moveTo(val[k + 0], val[k + 1]);
+ currentSegmentStartX = currentX;
+ currentSegmentStartY = currentY;
}
break;
- case 'l':
- cx += val[k + 0];
- cy += val[k + 1];
- path.lineTo(cx, cy);
+ case 'l': // lineto - Draw a line from the current point (relative)
+ path.rLineTo(val[k + 0], val[k + 1]);
+ currentX += val[k + 0];
+ currentY += val[k + 1];
break;
- case 'L':
- cx = val[k + 0];
- cy = val[k + 1];
- path.lineTo(cx, cy);
+ case 'L': // lineto - Draw a line from the current point
+ path.lineTo(val[k + 0], val[k + 1]);
+ currentX = val[k + 0];
+ currentY = val[k + 1];
break;
- case 'z':
- case 'Z':
- path.closePath();
- cx = loopX;
- cy = loopY;
+ case 'h': // horizontal lineto - Draws a horizontal line (relative)
+ path.rLineTo(val[k + 0], 0);
+ currentX += val[k + 0];
break;
- case 'h':
- cx += val[k + 0];
- path.lineTo(cx, cy);
+ case 'H': // horizontal lineto - Draws a horizontal line
+ path.lineTo(val[k + 0], currentY);
+ currentX = val[k + 0];
break;
- case 'H':
- path.lineTo(val[k + 0], cy);
- cx = val[k + 0];
+ case 'v': // vertical lineto - Draws a vertical line from the current point (r)
+ path.rLineTo(0, val[k + 0]);
+ currentY += val[k + 0];
break;
- case 'v':
- cy += val[k + 0];
- path.lineTo(cx, cy);
+ case 'V': // vertical lineto - Draws a vertical line from the current point
+ path.lineTo(currentX, val[k + 0]);
+ currentY = val[k + 0];
break;
- case 'V':
- path.lineTo(cx, val[k + 0]);
- cy = val[k + 0];
- break;
- case 'c':
- path.curveTo(cx + val[k + 0], cy + val[k + 1], cx + val[k + 2],
- cy + val[k + 3], cx + val[k + 4], cy + val[k + 5]);
- cpx = cx + val[k + 2];
- cpy = cy + val[k + 3];
- cx += val[k + 4];
- cy += val[k + 5];
- break;
- case 'C':
- path.curveTo(val[k + 0], val[k + 1], val[k + 2], val[k + 3],
+ case 'c': // curveto - Draws a cubic Bézier curve (relative)
+ path.rCubicTo(val[k + 0], val[k + 1], val[k + 2], val[k + 3],
val[k + 4], val[k + 5]);
- cx = val[k + 4];
- cy = val[k + 5];
- cpx = val[k + 2];
- cpy = val[k + 3];
- break;
- case 's':
- reflectCtrl = (lastCmd == 'c' || lastCmd == 's' || lastCmd == 'C' ||
- lastCmd == 'S');
- path.curveTo(reflectCtrl ? 2 * cx - cpx : cx, reflectCtrl ? 2
- * cy - cpy : cy, cx + val[k + 0], cy + val[k + 1], cx
- + val[k + 2], cy + val[k + 3]);
- cpx = cx + val[k + 0];
- cpy = cy + val[k + 1];
- cx += val[k + 2];
- cy += val[k + 3];
+ ctrlPointX = currentX + val[k + 2];
+ ctrlPointY = currentY + val[k + 3];
+ currentX += val[k + 4];
+ currentY += val[k + 5];
+
break;
- case 'S':
- reflectCtrl = (lastCmd == 'c' || lastCmd == 's' || lastCmd == 'C' ||
- lastCmd == 'S');
- path.curveTo(reflectCtrl ? 2 * cx - cpx : cx, reflectCtrl ? 2
- * cy - cpy : cy, val[k + 0], val[k + 1], val[k + 2],
- val[k + 3]);
- cpx = (val[k + 0]);
- cpy = (val[k + 1]);
- cx = val[k + 2];
- cy = val[k + 3];
+ case 'C': // curveto - Draws a cubic Bézier curve
+ path.cubicTo(val[k + 0], val[k + 1], val[k + 2], val[k + 3],
+ val[k + 4], val[k + 5]);
+ currentX = val[k + 4];
+ currentY = val[k + 5];
+ ctrlPointX = val[k + 2];
+ ctrlPointY = val[k + 3];
break;
- case 'q':
- path.quadTo(cx + val[k + 0], cy + val[k + 1], cx + val[k + 2],
- cy + val[k + 3]);
- cpx = cx + val[k + 0];
- cpy = cy + val[k + 1];
- // Note that we have to update cpx first, since cx will be updated here.
- cx += val[k + 2];
- cy += val[k + 3];
+ case 's': // smooth curveto - Draws a cubic Bézier curve (reflective cp)
+ reflectiveCtrlPointX = 0;
+ reflectiveCtrlPointY = 0;
+ if (previousCmd == 'c' || previousCmd == 's'
+ || previousCmd == 'C' || previousCmd == 'S') {
+ reflectiveCtrlPointX = currentX - ctrlPointX;
+ reflectiveCtrlPointY = currentY - ctrlPointY;
+ }
+ path.rCubicTo(reflectiveCtrlPointX, reflectiveCtrlPointY,
+ val[k + 0], val[k + 1],
+ val[k + 2], val[k + 3]);
+
+ ctrlPointX = currentX + val[k + 0];
+ ctrlPointY = currentY + val[k + 1];
+ currentX += val[k + 2];
+ currentY += val[k + 3];
break;
- case 'Q':
+ case 'S': // shorthand/smooth curveto Draws a cubic Bézier curve(reflective cp)
+ reflectiveCtrlPointX = currentX;
+ reflectiveCtrlPointY = currentY;
+ if (previousCmd == 'c' || previousCmd == 's'
+ || previousCmd == 'C' || previousCmd == 'S') {
+ reflectiveCtrlPointX = 2 * currentX - ctrlPointX;
+ reflectiveCtrlPointY = 2 * currentY - ctrlPointY;
+ }
+ path.cubicTo(reflectiveCtrlPointX, reflectiveCtrlPointY,
+ val[k + 0], val[k + 1], val[k + 2], val[k + 3]);
+ ctrlPointX = val[k + 0];
+ ctrlPointY = val[k + 1];
+ currentX = val[k + 2];
+ currentY = val[k + 3];
+ break;
+ case 'q': // Draws a quadratic Bézier (relative)
+ path.rQuadTo(val[k + 0], val[k + 1], val[k + 2], val[k + 3]);
+ ctrlPointX = currentX + val[k + 0];
+ ctrlPointY = currentY + val[k + 1];
+ currentX += val[k + 2];
+ currentY += val[k + 3];
+ break;
+ case 'Q': // Draws a quadratic Bézier
path.quadTo(val[k + 0], val[k + 1], val[k + 2], val[k + 3]);
- cx = val[k + 2];
- cy = val[k + 3];
- cpx = val[k + 0];
- cpy = val[k + 1];
+ ctrlPointX = val[k + 0];
+ ctrlPointY = val[k + 1];
+ currentX = val[k + 2];
+ currentY = val[k + 3];
break;
- case 't':
- reflectCtrl = (lastCmd == 'q' || lastCmd == 't' || lastCmd == 'Q' ||
- lastCmd == 'T');
- tempReflectedX = reflectCtrl ? 2 * cx - cpx : cx;
- tempReflectedY = reflectCtrl ? 2 * cy - cpy : cy;
- path.quadTo(tempReflectedX, tempReflectedY, cx + val[k + 0],
- cy + val[k + 1]);
- cpx = tempReflectedX;
- cpy = tempReflectedY;
- cx += val[k + 0];
- cy += val[k + 1];
+ case 't': // Draws a quadratic Bézier curve(reflective control point)(relative)
+ reflectiveCtrlPointX = 0;
+ reflectiveCtrlPointY = 0;
+ if (previousCmd == 'q' || previousCmd == 't'
+ || previousCmd == 'Q' || previousCmd == 'T') {
+ reflectiveCtrlPointX = currentX - ctrlPointX;
+ reflectiveCtrlPointY = currentY - ctrlPointY;
+ }
+ path.rQuadTo(reflectiveCtrlPointX, reflectiveCtrlPointY,
+ val[k + 0], val[k + 1]);
+ ctrlPointX = currentX + reflectiveCtrlPointX;
+ ctrlPointY = currentY + reflectiveCtrlPointY;
+ currentX += val[k + 0];
+ currentY += val[k + 1];
break;
- case 'T':
- reflectCtrl = (lastCmd == 'q' || lastCmd == 't' || lastCmd == 'Q' ||
- lastCmd == 'T');
- tempReflectedX = reflectCtrl ? 2 * cx - cpx : cx;
- tempReflectedY = reflectCtrl ? 2 * cy - cpy : cy;
- path.quadTo(tempReflectedX, tempReflectedY, val[k + 0], val[k + 1]);
- cx = val[k + 0];
- cy = val[k + 1];
- cpx = tempReflectedX;
- cpy = tempReflectedY;
+ case 'T': // Draws a quadratic Bézier curve (reflective control point)
+ reflectiveCtrlPointX = currentX;
+ reflectiveCtrlPointY = currentY;
+ if (previousCmd == 'q' || previousCmd == 't'
+ || previousCmd == 'Q' || previousCmd == 'T') {
+ reflectiveCtrlPointX = 2 * currentX - ctrlPointX;
+ reflectiveCtrlPointY = 2 * currentY - ctrlPointY;
+ }
+ path.quadTo(reflectiveCtrlPointX, reflectiveCtrlPointY,
+ val[k + 0], val[k + 1]);
+ ctrlPointX = reflectiveCtrlPointX;
+ ctrlPointY = reflectiveCtrlPointY;
+ currentX = val[k + 0];
+ currentY = val[k + 1];
break;
- case 'a':
+ case 'a': // Draws an elliptical arc
// (rx ry x-axis-rotation large-arc-flag sweep-flag x y)
- drawArc(path, cx, cy, val[k + 5] + cx, val[k + 6] + cy,
- val[k + 0], val[k + 1], val[k + 2], val[k + 3] != 0,
+ drawArc(path,
+ currentX,
+ currentY,
+ val[k + 5] + currentX,
+ val[k + 6] + currentY,
+ val[k + 0],
+ val[k + 1],
+ val[k + 2],
+ val[k + 3] != 0,
val[k + 4] != 0);
- cx += val[k + 5];
- cy += val[k + 6];
- cpx = cx;
- cpy = cy;
-
+ currentX += val[k + 5];
+ currentY += val[k + 6];
+ ctrlPointX = currentX;
+ ctrlPointY = currentY;
break;
- case 'A':
- drawArc(path, cx, cy, val[k + 5], val[k + 6], val[k + 0],
- val[k + 1], val[k + 2], val[k + 3] != 0,
+ case 'A': // Draws an elliptical arc
+ drawArc(path,
+ currentX,
+ currentY,
+ val[k + 5],
+ val[k + 6],
+ val[k + 0],
+ val[k + 1],
+ val[k + 2],
+ val[k + 3] != 0,
val[k + 4] != 0);
- cx = val[k + 5];
- cy = val[k + 6];
- cpx = cx;
- cpy = cy;
+ currentX = val[k + 5];
+ currentY = val[k + 6];
+ ctrlPointX = currentX;
+ ctrlPointY = currentY;
break;
-
}
- lastCmd = cmd;
+ previousCmd = cmd;
}
- current[0] = cx;
- current[1] = cy;
- current[2] = cpx;
- current[3] = cpy;
- current[4] = loopX;
- current[5] = loopY;
-
+ current[0] = currentX;
+ current[1] = currentY;
+ current[2] = ctrlPointX;
+ current[3] = ctrlPointY;
+ current[4] = currentSegmentStartX;
+ current[5] = currentSegmentStartY;
}
- private static void drawArc(@NonNull Path2D p, float x0, float y0, float x1,
+ private static void drawArc(@NonNull Path_Delegate p, float x0, float y0, float x1,
float y1, float a, float b, float theta, boolean isMoreThanHalf,
boolean isPositiveArc) {
@@ -707,7 +790,7 @@
* @param start The start angle of the arc on the ellipse
* @param sweep The angle (positive or negative) of the sweep of the arc on the ellipse
*/
- private static void arcToBezier(@NonNull Path2D p, double cx, double cy, double a,
+ private static void arcToBezier(@NonNull Path_Delegate p, double cx, double cy, double a,
double b, double e1x, double e1y, double theta, double start,
double sweep) {
// Taken from equations at:
@@ -744,8 +827,12 @@
double q2x = e2x - alpha * ep2x;
double q2y = e2y - alpha * ep2y;
- p.curveTo((float) q1x, (float) q1y, (float) q2x, (float) q2y,
- (float) e2x, (float) e2y);
+ p.cubicTo((float) q1x,
+ (float) q1y,
+ (float) q2x,
+ (float) q2y,
+ (float) e2x,
+ (float) e2y);
eta1 = eta2;
e1x = e2x;
e1y = e2y;
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java
index 85e2610..4039cdf 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java
@@ -484,6 +484,12 @@
}
@Override
+ public Drawable getManagedUserBadgedDrawable(Drawable drawable, Rect badgeLocation,
+ int badgeDensity) {
+ return null;
+ }
+
+ @Override
public Drawable getUserBadgedIcon(Drawable icon, UserHandle user) {
return null;
}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
index 99af226..53f1912 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
@@ -60,6 +60,7 @@
import android.graphics.Bitmap;
import android.graphics.Bitmap_Delegate;
import android.graphics.Canvas;
+import android.os.Looper;
import android.preference.Preference_Delegate;
import android.view.AttachInfo_Accessor;
import android.view.BridgeInflater;
@@ -1398,6 +1399,14 @@
}
public void dispose() {
+ boolean createdLooper = false;
+ if (Looper.myLooper() == null) {
+ // Detaching the root view from the window will try to stop any running animations.
+ // The stop method checks that it can run in the looper so, if there is no current
+ // looper, we create a temporary one to complete the shutdown.
+ Bridge.prepareThread();
+ createdLooper = true;
+ }
AttachInfo_Accessor.detachFromWindow(mViewRoot);
if (mCanvas != null) {
mCanvas.release();
@@ -1412,5 +1421,9 @@
mImage = null;
mViewRoot = null;
mContentRoot = null;
+
+ if (createdLooper) {
+ Bridge.cleanupThread();
+ }
}
}
diff --git a/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/Main.java b/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/Main.java
index 6b23da7..2726042 100644
--- a/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/Main.java
+++ b/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/Main.java
@@ -335,7 +335,7 @@
.setNavigation(Navigation.NONAV);
SessionParams params = getSessionParams(parser, customConfigGenerator,
- layoutLibCallback, "Theme.Material.NoActionBar.Fullscreen", false,
+ layoutLibCallback, "Theme.Material.Light.NoActionBar.Fullscreen", false,
RenderingMode.V_SCROLL, 22);
renderAndVerify(params, "expand_vert_layout.png");
@@ -348,7 +348,7 @@
parser = new LayoutPullParser(APP_TEST_RES + "/layout/" +
"expand_horz_layout.xml");
params = getSessionParams(parser, customConfigGenerator,
- layoutLibCallback, "Theme.Material.NoActionBar.Fullscreen", false,
+ layoutLibCallback, "Theme.Material.Light.NoActionBar.Fullscreen", false,
RenderingMode.H_SCROLL, 22);
renderAndVerify(params, "expand_horz_layout.png");
diff --git a/tools/layoutlib/create/create.iml b/tools/layoutlib/create/create.iml
index b2b14b4..368b46b 100644
--- a/tools/layoutlib/create/create.iml
+++ b/tools/layoutlib/create/create.iml
@@ -22,6 +22,6 @@
</SOURCES>
</library>
</orderEntry>
- <orderEntry type="library" scope="TEST" name="JUnit4" level="application" />
+ <orderEntry type="library" scope="TEST" name="junit" level="project" />
</component>
</module>
\ No newline at end of file
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
index 8a23e4b..8c3bd2f 100644
--- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
@@ -269,6 +269,7 @@
"android.graphics.SweepGradient",
"android.graphics.Typeface",
"android.graphics.Xfermode",
+ "android.graphics.drawable.VectorDrawable",
"android.os.SystemClock",
"android.os.SystemProperties",
"android.text.AndroidBidi",
@@ -321,7 +322,12 @@
"org.kxml2.io.KXmlParser"
};
+ /**
+ * List of fields for which we will update the visibility to be public. This is sometimes
+ * needed when access from the delegate classes is needed.
+ */
private final static String[] PROMOTED_FIELDS = new String[] {
+ "android.graphics.drawable.VectorDrawable#mVectorState",
"android.view.Choreographer#mLastFrameTimeNanos"
};
diff --git a/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/DelegateClassAdapterTest.java b/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/DelegateClassAdapterTest.java
index 0912fb1..afaa399 100644
--- a/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/DelegateClassAdapterTest.java
+++ b/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/DelegateClassAdapterTest.java
@@ -53,12 +53,10 @@
private MockLog mLog;
- private static final String NATIVE_CLASS_NAME = ClassWithNative.class.getCanonicalName();
- private static final String OUTER_CLASS_NAME = OuterClass.class.getCanonicalName();
- private static final String INNER_CLASS_NAME = OuterClass.class.getCanonicalName() + "$" +
- InnerClass.class.getSimpleName();
- private static final String STATIC_INNER_CLASS_NAME =
- OuterClass.class.getCanonicalName() + "$" + StaticInnerClass.class.getSimpleName();
+ private static final String NATIVE_CLASS_NAME = ClassWithNative.class.getName();
+ private static final String OUTER_CLASS_NAME = OuterClass.class.getName();
+ private static final String INNER_CLASS_NAME = InnerClass.class.getName();
+ private static final String STATIC_INNER_CLASS_NAME = StaticInnerClass.class.getName();
@Before
public void setUp() throws Exception {
@@ -69,12 +67,12 @@
/**
* Tests that a class not being modified still works.
*/
- @SuppressWarnings("unchecked")
@Test
public void testNoOp() throws Throwable {
// create an instance of the class that will be modified
// (load the class in a distinct class loader so that we can trash its definition later)
ClassLoader cl1 = new ClassLoader(this.getClass().getClassLoader()) { };
+ @SuppressWarnings("unchecked")
Class<ClassWithNative> clazz1 = (Class<ClassWithNative>) cl1.loadClass(NATIVE_CLASS_NAME);
ClassWithNative instance1 = clazz1.newInstance();
assertEquals(42, instance1.add(20, 22));
diff --git a/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/StubMethodAdapterTest.java b/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/StubMethodAdapterTest.java
new file mode 100644
index 0000000..3db3e23
--- /dev/null
+++ b/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/StubMethodAdapterTest.java
@@ -0,0 +1,132 @@
+/*
+ * 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.
+ */
+
+package com.android.tools.layoutlib.create;
+
+import com.android.tools.layoutlib.create.dataclass.StubClass;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.objectweb.asm.ClassReader;
+import org.objectweb.asm.ClassVisitor;
+import org.objectweb.asm.ClassWriter;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.Type;
+
+import java.lang.reflect.Method;
+import java.util.function.BiPredicate;
+import java.util.function.Consumer;
+
+import static org.junit.Assert.*;
+
+public class StubMethodAdapterTest {
+
+ private static final String STUB_CLASS_NAME = StubClass.class.getName();
+
+ /**
+ * Load a dummy class, stub one of its method and ensure that the modified class works as
+ * intended.
+ */
+ @Test
+ public void testBoolean() throws Exception {
+ final String methodName = "returnTrue";
+ // First don't change the method and assert that it returns true
+ testBoolean((name, type) -> false, Assert::assertTrue, methodName);
+ // Change the method now and assert that it returns false.
+ testBoolean((name, type) -> methodName.equals(name) &&
+ Type.BOOLEAN_TYPE.equals(type.getReturnType()), Assert::assertFalse, methodName);
+ }
+
+ /**
+ * @param methodPredicate tests if the method should be replaced
+ */
+ private void testBoolean(BiPredicate<String, Type> methodPredicate, Consumer<Boolean> assertion,
+ String methodName) throws Exception {
+ ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS);
+ // Always rename the class to avoid conflict with the original class.
+ String newClassName = STUB_CLASS_NAME + '_';
+ new ClassReader(STUB_CLASS_NAME).accept(
+ new ClassAdapter(newClassName, writer, methodPredicate), 0);
+ MyClassLoader myClassLoader = new MyClassLoader(newClassName, writer.toByteArray());
+ Class<?> aClass = myClassLoader.loadClass(newClassName);
+ assertTrue("StubClass not loaded by the classloader. Likely a bug in the test.",
+ myClassLoader.findClassCalled);
+ Method method = aClass.getMethod(methodName);
+ Object o = aClass.newInstance();
+ assertion.accept((Boolean) method.invoke(o));
+ }
+
+ private static class ClassAdapter extends ClassVisitor {
+
+ private final String mClassName;
+ private final BiPredicate<String, Type> mMethodPredicate;
+
+ private ClassAdapter(String className, ClassVisitor cv,
+ BiPredicate<String, Type> methodPredicate) {
+ super(Main.ASM_VERSION, cv);
+ mClassName = className.replace('.', '/');
+ mMethodPredicate = methodPredicate;
+ }
+
+ @Override
+ public void visit(int version, int access, String name, String signature, String superName,
+ String[] interfaces) {
+ super.visit(version, access, mClassName, signature, superName,
+ interfaces);
+ }
+
+ @Override
+ public MethodVisitor visitMethod(int access, String name, String desc, String signature,
+ String[] exceptions) {
+ // Copied partly from
+ // com.android.tools.layoutlib.create.DelegateClassAdapter.visitMethod()
+ // but not generating the _Original method.
+ boolean isStatic = (access & Opcodes.ACC_STATIC) != 0;
+ boolean isNative = (access & Opcodes.ACC_NATIVE) != 0;
+ MethodVisitor originalMethod =
+ super.visitMethod(access, name, desc, signature, exceptions);
+ Type descriptor = Type.getMethodType(desc);
+ if (mMethodPredicate.test(name, descriptor)) {
+ String methodSignature = mClassName + "#" + name;
+ String invokeSignature = methodSignature + desc;
+ return new StubMethodAdapter(originalMethod, name, descriptor.getReturnType(),
+ invokeSignature, isStatic, isNative);
+ }
+ return originalMethod;
+ }
+ }
+
+ private static class MyClassLoader extends ClassLoader {
+ private final String mName;
+ private final byte[] mBytes;
+ private boolean findClassCalled;
+
+ private MyClassLoader(String name, byte[] bytes) {
+ mName = name;
+ mBytes = bytes;
+ }
+
+ @Override
+ protected Class<?> findClass(String name) throws ClassNotFoundException {
+ if (name.equals(mName)) {
+ findClassCalled = true;
+ return defineClass(name, mBytes, 0, mBytes.length);
+ }
+ return super.findClass(name);
+ }
+ }
+}
diff --git a/core/java/android/hardware/ICameraServiceListener.aidl b/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/dataclass/StubClass.java
similarity index 62%
rename from core/java/android/hardware/ICameraServiceListener.aidl
rename to tools/layoutlib/create/tests/com/android/tools/layoutlib/create/dataclass/StubClass.java
index 49278b6..3ae8e47 100644
--- a/core/java/android/hardware/ICameraServiceListener.aidl
+++ b/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/dataclass/StubClass.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 The Android Open Source Project
+ * 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.
@@ -14,15 +14,17 @@
* limitations under the License.
*/
-package android.hardware;
+package com.android.tools.layoutlib.create.dataclass;
-/** @hide */
-interface ICameraServiceListener
-{
- /**
- * Keep up-to-date with frameworks/av/include/camera/ICameraServiceListener.h
- */
- void onStatusChanged(int status, int cameraId);
+import com.android.tools.layoutlib.create.StubMethodAdapterTest;
- void onTorchStatusChanged(int status, String cameraId);
+/**
+ * Used by {@link StubMethodAdapterTest}
+ */
+@SuppressWarnings("unused")
+public class StubClass {
+
+ public boolean returnTrue() {
+ return true;
+ }
}
diff --git a/wifi/java/android/net/wifi/RttManager.java b/wifi/java/android/net/wifi/RttManager.java
index 59416b8..13abaff 100644
--- a/wifi/java/android/net/wifi/RttManager.java
+++ b/wifi/java/android/net/wifi/RttManager.java
@@ -300,7 +300,7 @@
try {
mRttCapabilities = mService.getRttCapabilities();
} catch (RemoteException e) {
- Log.e(TAG, "Can not get RTT Capabilities");
+ throw e.rethrowFromSystemServer();
}
}
return mRttCapabilities;
@@ -1132,7 +1132,7 @@
Log.d(TAG, "Get the messenger from " + mService);
messenger = mService.getMessenger();
} catch (RemoteException e) {
- /* do nothing */
+ throw e.rethrowFromSystemServer();
} catch (SecurityException e) {
/* do nothing */
}
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index ddd8f43..7dc8049 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -1357,6 +1357,7 @@
append(" PROVIDER-NAME: ").append(this.providerFriendlyName).
append(" BSSID: ").append(this.BSSID).append(" FQDN: ").append(this.FQDN)
.append(" PRIO: ").append(this.priority)
+ .append(" HIDDEN: ").append(this.hiddenSSID)
.append('\n');
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 4921073..a5bfd3c 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -39,9 +39,9 @@
import android.util.Log;
import android.util.SparseArray;
-import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.AsyncChannel;
import com.android.internal.util.Protocol;
+import com.android.server.net.NetworkPinner;
import java.net.InetAddress;
import java.util.ArrayList;
@@ -678,11 +678,6 @@
private static int sThreadRefCount;
private static HandlerThread sHandlerThread;
- @GuardedBy("sCM")
- // TODO: Introduce refcounting and make this a per-process static callback, instead of a
- // per-WifiManager callback.
- private PinningNetworkCallback mNetworkCallback;
-
/**
* Create a new WifiManager instance.
* Applications will almost always want to use
@@ -723,8 +718,7 @@
try {
return mService.getConfiguredNetworks();
} catch (RemoteException e) {
- Log.w(TAG, "Caught RemoteException trying to get configured networks: " + e);
- return null;
+ throw e.rethrowFromSystemServer();
}
}
@@ -734,7 +728,7 @@
try {
return mService.getPrivilegedConfiguredNetworks();
} catch (RemoteException e) {
- return null;
+ throw e.rethrowFromSystemServer();
}
}
@@ -744,7 +738,7 @@
try {
return mService.getConnectionStatistics();
} catch (RemoteException e) {
- return null;
+ throw e.rethrowFromSystemServer();
}
}
@@ -758,7 +752,7 @@
try {
return mService.getMatchingWifiConfig(scanResult);
} catch (RemoteException e) {
- return null;
+ throw e.rethrowFromSystemServer();
}
}
@@ -818,7 +812,7 @@
try {
return mService.addOrUpdateNetwork(config);
} catch (RemoteException e) {
- return -1;
+ throw e.rethrowFromSystemServer();
}
}
@@ -832,7 +826,7 @@
try {
return mService.addPasspointManagementObject(mo);
} catch (RemoteException e) {
- return -1;
+ throw e.rethrowFromSystemServer();
}
}
@@ -848,7 +842,7 @@
try {
return mService.modifyPasspointManagementObject(fqdn, mos);
} catch (RemoteException e) {
- return -1;
+ throw e.rethrowFromSystemServer();
}
}
@@ -862,6 +856,7 @@
try {
mService.queryPasspointIcon(bssid, fileName);
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
@@ -875,7 +870,7 @@
try {
return mService.matchProviderWithCurrentNetwork(fqdn);
} catch (RemoteException e) {
- return -1;
+ throw e.rethrowFromSystemServer();
}
}
@@ -889,28 +884,11 @@
try {
mService.deauthenticateNetwork(holdoff, ess);
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
/**
- * Sets whether or not the given network is metered from a network policy
- * point of view. A network should be classified as metered when the user is
- * sensitive to heavy data usage on that connection due to monetary costs,
- * data limitations or battery/performance issues. A typical example would
- * be a wifi connection where the user was being charged for usage.
- * @param netId the integer that identifies the network configuration
- * to the supplicant.
- * @param isMetered True to mark the network as metered.
- * @return {@code true} if the operation succeeded.
- * @hide
- */
- @SystemApi
- public boolean setMetered(int netId, boolean isMetered) {
- // TODO(jjoslin): Implement
- return false;
- }
-
- /**
* Remove the specified network from the list of configured networks.
* This may result in the asynchronous delivery of state change
* events.
@@ -922,7 +900,7 @@
try {
return mService.removeNetwork(netId);
} catch (RemoteException e) {
- return false;
+ throw e.rethrowFromSystemServer();
}
}
@@ -955,18 +933,22 @@
public boolean enableNetwork(int netId, boolean disableOthers) {
final boolean pin = disableOthers && mTargetSdkVersion < Build.VERSION_CODES.LOLLIPOP;
if (pin) {
- registerPinningNetworkCallback();
+ NetworkRequest request = new NetworkRequest.Builder()
+ .clearCapabilities()
+ .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
+ .build();
+ NetworkPinner.pin(mContext, request);
}
boolean success;
try {
success = mService.enableNetwork(netId, disableOthers);
} catch (RemoteException e) {
- success = false;
+ throw e.rethrowFromSystemServer();
}
if (pin && !success) {
- unregisterPinningNetworkCallback();
+ NetworkPinner.unpin();
}
return success;
@@ -983,7 +965,7 @@
try {
return mService.disableNetwork(netId);
} catch (RemoteException e) {
- return false;
+ throw e.rethrowFromSystemServer();
}
}
@@ -997,7 +979,7 @@
mService.disconnect();
return true;
} catch (RemoteException e) {
- return false;
+ throw e.rethrowFromSystemServer();
}
}
@@ -1012,7 +994,7 @@
mService.reconnect();
return true;
} catch (RemoteException e) {
- return false;
+ throw e.rethrowFromSystemServer();
}
}
@@ -1027,7 +1009,7 @@
mService.reassociate();
return true;
} catch (RemoteException e) {
- return false;
+ throw e.rethrowFromSystemServer();
}
}
@@ -1042,7 +1024,7 @@
try {
return mService.pingSupplicant();
} catch (RemoteException e) {
- return false;
+ throw e.rethrowFromSystemServer();
}
}
@@ -1090,7 +1072,7 @@
try {
return mService.getSupportedFeatures();
} catch (RemoteException e) {
- return 0;
+ throw e.rethrowFromSystemServer();
}
}
@@ -1216,9 +1198,8 @@
return mService.reportActivityInfo();
}
} catch (RemoteException e) {
- Log.e(TAG, "getControllerActivityEnergyInfo: " + e);
+ throw e.rethrowFromSystemServer();
}
- return null;
}
/**
@@ -1232,7 +1213,7 @@
mService.startScan(null, null);
return true;
} catch (RemoteException e) {
- return false;
+ throw e.rethrowFromSystemServer();
}
}
@@ -1243,7 +1224,7 @@
mService.startScan(null, workSource);
return true;
} catch (RemoteException e) {
- return false;
+ throw e.rethrowFromSystemServer();
}
}
@@ -1299,7 +1280,7 @@
try {
return mService.getWpsNfcConfigurationToken(netId);
} catch (RemoteException e) {
- return null;
+ throw e.rethrowFromSystemServer();
}
}
@@ -1311,7 +1292,7 @@
try {
return mService.getConnectionInfo();
} catch (RemoteException e) {
- return null;
+ throw e.rethrowFromSystemServer();
}
}
@@ -1328,7 +1309,7 @@
try {
return mService.getScanResults(mContext.getOpPackageName());
} catch (RemoteException e) {
- return new ArrayList<ScanResult>();
+ throw e.rethrowFromSystemServer();
}
}
@@ -1344,7 +1325,7 @@
try {
return mService.isScanAlwaysAvailable();
} catch (RemoteException e) {
- return false;
+ throw e.rethrowFromSystemServer();
}
}
@@ -1361,7 +1342,7 @@
try {
return mService.saveConfiguration();
} catch (RemoteException e) {
- return false;
+ throw e.rethrowFromSystemServer();
}
}
@@ -1375,7 +1356,9 @@
public void setCountryCode(String country, boolean persist) {
try {
mService.setCountryCode(country, persist);
- } catch (RemoteException e) { }
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
}
/**
@@ -1387,9 +1370,9 @@
public String getCountryCode() {
try {
String country = mService.getCountryCode();
- return(country);
+ return country;
} catch (RemoteException e) {
- return null;
+ throw e.rethrowFromSystemServer();
}
}
@@ -1405,7 +1388,9 @@
public void setFrequencyBand(int band, boolean persist) {
try {
mService.setFrequencyBand(band, persist);
- } catch (RemoteException e) { }
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
}
/**
@@ -1421,7 +1406,7 @@
try {
return mService.getFrequencyBand();
} catch (RemoteException e) {
- return -1;
+ throw e.rethrowFromSystemServer();
}
}
@@ -1434,7 +1419,7 @@
try {
return mService.isDualBandSupported();
} catch (RemoteException e) {
- return false;
+ throw e.rethrowFromSystemServer();
}
}
@@ -1447,7 +1432,7 @@
try {
return mService.getDhcpInfo();
} catch (RemoteException e) {
- return null;
+ throw e.rethrowFromSystemServer();
}
}
@@ -1461,7 +1446,7 @@
try {
return mService.setWifiEnabled(enabled);
} catch (RemoteException e) {
- return false;
+ throw e.rethrowFromSystemServer();
}
}
@@ -1476,7 +1461,7 @@
try {
return mService.getWifiEnabledState();
} catch (RemoteException e) {
- return WIFI_STATE_UNKNOWN;
+ throw e.rethrowFromSystemServer();
}
}
@@ -1553,7 +1538,7 @@
mService.setWifiApEnabled(wifiConfig, enabled);
return true;
} catch (RemoteException e) {
- return false;
+ throw e.rethrowFromSystemServer();
}
}
@@ -1571,7 +1556,7 @@
try {
return mService.getWifiApEnabledState();
} catch (RemoteException e) {
- return WIFI_AP_STATE_FAILED;
+ throw e.rethrowFromSystemServer();
}
}
@@ -1598,7 +1583,7 @@
try {
return mService.getWifiApConfiguration();
} catch (RemoteException e) {
- return null;
+ throw e.rethrowFromSystemServer();
}
}
@@ -1612,8 +1597,7 @@
try {
return mService.buildWifiConfig(uriString, mimeType, data);
} catch (RemoteException e) {
- Log.w(TAG, "Caught RemoteException trying to build wifi config: " + e);
- return null;
+ throw e.rethrowFromSystemServer();
}
}
@@ -1629,7 +1613,7 @@
mService.setWifiApConfiguration(wifiConfig);
return true;
} catch (RemoteException e) {
- return false;
+ throw e.rethrowFromSystemServer();
}
}
@@ -1646,7 +1630,7 @@
mService.addToBlacklist(bssid);
return true;
} catch (RemoteException e) {
- return false;
+ throw e.rethrowFromSystemServer();
}
}
@@ -1663,7 +1647,7 @@
mService.clearBlacklist();
return true;
} catch (RemoteException e) {
- return false;
+ throw e.rethrowFromSystemServer();
}
}
@@ -1692,7 +1676,7 @@
try {
mService.enableTdls(remoteIPAddress.getHostAddress(), enable);
} catch (RemoteException e) {
- // Just ignore the exception
+ throw e.rethrowFromSystemServer();
}
}
@@ -1706,7 +1690,7 @@
try {
mService.enableTdlsWithMacAddress(remoteMacAddress, enable);
} catch (RemoteException e) {
- // Just ignore the exception
+ throw e.rethrowFromSystemServer();
}
}
@@ -2012,100 +1996,6 @@
"No permission to access and change wifi or a bad initialization");
}
- private void initConnectivityManager() {
- // TODO: what happens if an app calls a WifiManager API before ConnectivityManager is
- // registered? Can we fix this by starting ConnectivityService before WifiService?
- if (sCM == null) {
- sCM = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
- if (sCM == null) {
- throw new IllegalStateException("Bad luck, ConnectivityService not started.");
- }
- }
- }
-
- /**
- * A NetworkCallback that pins the process to the first wifi network to connect.
- *
- * We use this to maintain compatibility with pre-M apps that call WifiManager.enableNetwork()
- * to connect to a Wi-Fi network that has no Internet access, and then assume that they will be
- * able to use that network because it's the system default.
- *
- * In order to maintain compatibility with apps that call setProcessDefaultNetwork themselves,
- * we try not to set the default network unless they have already done so, and we try not to
- * clear the default network unless we set it ourselves.
- *
- * This should maintain behaviour that's compatible with L, which would pin the whole system to
- * any wifi network that was created via enableNetwork(..., true) until that network
- * disconnected.
- *
- * Note that while this hack allows network traffic to flow, it is quite limited. For example:
- *
- * 1. setProcessDefaultNetwork only affects this process, so:
- * - Any subprocesses spawned by this process will not be pinned to Wi-Fi.
- * - If this app relies on any other apps on the device also being on Wi-Fi, that won't work
- * either, because other apps on the device will not be pinned.
- * 2. The behaviour of other APIs is not modified. For example:
- * - getActiveNetworkInfo will return the system default network, not Wi-Fi.
- * - There will be no CONNECTIVITY_ACTION broadcasts about TYPE_WIFI.
- * - getProcessDefaultNetwork will not return null, so if any apps are relying on that, they
- * will be surprised as well.
- */
- private class PinningNetworkCallback extends NetworkCallback {
- private Network mPinnedNetwork;
-
- @Override
- public void onPreCheck(Network network) {
- if (sCM.getProcessDefaultNetwork() == null && mPinnedNetwork == null) {
- sCM.setProcessDefaultNetwork(network);
- mPinnedNetwork = network;
- Log.d(TAG, "Wifi alternate reality enabled on network " + network);
- }
- }
-
- @Override
- public void onLost(Network network) {
- if (network.equals(mPinnedNetwork) && network.equals(sCM.getProcessDefaultNetwork())) {
- sCM.setProcessDefaultNetwork(null);
- Log.d(TAG, "Wifi alternate reality disabled on network " + network);
- mPinnedNetwork = null;
- unregisterPinningNetworkCallback();
- }
- }
- }
-
- private void registerPinningNetworkCallback() {
- initConnectivityManager();
- synchronized (sCM) {
- if (mNetworkCallback == null) {
- // TODO: clear all capabilities.
- NetworkRequest request = new NetworkRequest.Builder()
- .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
- .removeCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
- .build();
- mNetworkCallback = new PinningNetworkCallback();
- try {
- sCM.registerNetworkCallback(request, mNetworkCallback);
- } catch (SecurityException e) {
- Log.d(TAG, "Failed to register network callback", e);
- }
- }
- }
- }
-
- private void unregisterPinningNetworkCallback() {
- initConnectivityManager();
- synchronized (sCM) {
- if (mNetworkCallback != null) {
- try {
- sCM.unregisterNetworkCallback(mNetworkCallback);
- } catch (SecurityException e) {
- Log.d(TAG, "Failed to unregister network callback", e);
- }
- mNetworkCallback = null;
- }
- }
- }
-
/**
* Connect to a network with the given configuration. The network also
* gets added to the supplicant configuration.
@@ -2219,6 +2109,7 @@
try {
mService.disableEphemeralNetwork(SSID);
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
@@ -2259,7 +2150,7 @@
try {
return mService.getWifiServiceMessenger();
} catch (RemoteException e) {
- return null;
+ throw e.rethrowFromSystemServer();
} catch (SecurityException e) {
return null;
}
@@ -2274,7 +2165,7 @@
try {
return mService.getConfigFile();
} catch (RemoteException e) {
- return null;
+ throw e.rethrowFromSystemServer();
}
}
@@ -2340,7 +2231,8 @@
}
mActiveLockCount++;
}
- } catch (RemoteException ignore) {
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
mHeld = true;
}
@@ -2367,7 +2259,8 @@
synchronized (WifiManager.this) {
mActiveLockCount--;
}
- } catch (RemoteException ignore) {
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
mHeld = false;
}
@@ -2427,6 +2320,7 @@
try {
mService.updateWifiLockWorkSource(mBinder, mWorkSource);
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -2456,7 +2350,8 @@
synchronized (WifiManager.this) {
mActiveLockCount--;
}
- } catch (RemoteException ignore) {
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
}
@@ -2572,7 +2467,8 @@
}
mActiveLockCount++;
}
- } catch (RemoteException ignore) {
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
mHeld = true;
}
@@ -2611,7 +2507,8 @@
synchronized (WifiManager.this) {
mActiveLockCount--;
}
- } catch (RemoteException ignore) {
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
mHeld = false;
}
@@ -2685,7 +2582,7 @@
try {
return mService.isMulticastEnabled();
} catch (RemoteException e) {
- return false;
+ throw e.rethrowFromSystemServer();
}
}
@@ -2698,7 +2595,7 @@
mService.initializeMulticastFiltering();
return true;
} catch (RemoteException e) {
- return false;
+ throw e.rethrowFromSystemServer();
}
}
@@ -2736,7 +2633,7 @@
try {
return mService.getVerboseLoggingLevel();
} catch (RemoteException e) {
- return 0;
+ throw e.rethrowFromSystemServer();
}
}
@@ -2748,7 +2645,7 @@
try {
mService.enableAggressiveHandover(enabled);
} catch (RemoteException e) {
-
+ throw e.rethrowFromSystemServer();
}
}
@@ -2761,7 +2658,7 @@
try {
return mService.getAggressiveHandover();
} catch (RemoteException e) {
- return 0;
+ throw e.rethrowFromSystemServer();
}
}
@@ -2773,7 +2670,7 @@
try {
mService.setAllowScansWithTraffic(enabled);
} catch (RemoteException e) {
-
+ throw e.rethrowFromSystemServer();
}
}
@@ -2785,7 +2682,7 @@
try {
return mService.getAllowScansWithTraffic();
} catch (RemoteException e) {
- return 0;
+ throw e.rethrowFromSystemServer();
}
}
@@ -2798,6 +2695,7 @@
try {
mService.factoryReset();
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
@@ -2810,7 +2708,7 @@
try {
return mService.getCurrentNetwork();
} catch (RemoteException e) {
- return null;
+ throw e.rethrowFromSystemServer();
}
}
@@ -2824,7 +2722,7 @@
try {
return mService.enableAutoJoinWhenAssociated(enabled);
} catch (RemoteException e) {
- return false;
+ throw e.rethrowFromSystemServer();
}
}
@@ -2836,7 +2734,7 @@
try {
return mService.getEnableAutoJoinWhenAssociated();
} catch (RemoteException e) {
- return false;
+ throw e.rethrowFromSystemServer();
}
}
/**
@@ -2847,7 +2745,7 @@
try {
mService.setHalBasedAutojoinOffload(enabled);
} catch (RemoteException e) {
-
+ throw e.rethrowFromSystemServer();
}
}
@@ -2859,7 +2757,7 @@
try {
return mService.getHalBasedAutojoinOffload();
} catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
- return 0;
}
}
diff --git a/wifi/java/android/net/wifi/nan/WifiNanManager.java b/wifi/java/android/net/wifi/nan/WifiNanManager.java
index 667c4b1..1b78beb 100644
--- a/wifi/java/android/net/wifi/nan/WifiNanManager.java
+++ b/wifi/java/android/net/wifi/nan/WifiNanManager.java
@@ -75,7 +75,7 @@
}
mService.connect(mBinder, listener.callback, events);
} catch (RemoteException e) {
- Log.w(TAG, "connect RemoteException (FYI - ignoring): " + e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -94,7 +94,7 @@
mService.disconnect(mBinder);
mBinder = null;
} catch (RemoteException e) {
- Log.w(TAG, "disconnect RemoteException (FYI - ignoring): " + e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -116,7 +116,7 @@
try {
mService.requestConfig(configRequest);
} catch (RemoteException e) {
- Log.w(TAG, "requestConfig RemoteException (FYI - ignoring): " + e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -173,8 +173,7 @@
if (DBG) Log.d(TAG, "publish: session created - sessionId=" + sessionId);
mService.publish(sessionId, publishData, publishSettings);
} catch (RemoteException e) {
- Log.w(TAG, "createSession/publish RemoteException: " + e);
- return null;
+ throw e.rethrowFromSystemServer();
}
return new WifiNanPublishSession(this, sessionId);
@@ -200,7 +199,7 @@
try {
mService.publish(sessionId, publishData, publishSettings);
} catch (RemoteException e) {
- Log.w(TAG, "publish RemoteException: " + e);
+ throw e.rethrowFromSystemServer();
}
}
/**
@@ -256,8 +255,7 @@
if (DBG) Log.d(TAG, "subscribe: session created - sessionId=" + sessionId);
mService.subscribe(sessionId, subscribeData, subscribeSettings);
} catch (RemoteException e) {
- Log.w(TAG, "createSession/subscribe RemoteException: " + e);
- return null;
+ throw e.rethrowFromSystemServer();
}
return new WifiNanSubscribeSession(this, sessionId);
@@ -286,7 +284,7 @@
try {
mService.subscribe(sessionId, subscribeData, subscribeSettings);
} catch (RemoteException e) {
- Log.w(TAG, "subscribe RemoteException: " + e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -299,7 +297,7 @@
try {
mService.stopSession(sessionId);
} catch (RemoteException e) {
- Log.w(TAG, "stopSession RemoteException (FYI - ignoring): " + e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -312,7 +310,7 @@
try {
mService.destroySession(sessionId);
} catch (RemoteException e) {
- Log.w(TAG, "destroySession RemoteException (FYI - ignoring): " + e);
+ throw e.rethrowFromSystemServer();
}
}
@@ -328,7 +326,7 @@
}
mService.sendMessage(sessionId, peerId, message, messageLength, messageId);
} catch (RemoteException e) {
- Log.w(TAG, "subscribe RemoteException (FYI - ignoring): " + e);
+ throw e.rethrowFromSystemServer();
}
}
}
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pManager.java b/wifi/java/android/net/wifi/p2p/WifiP2pManager.java
index 6409450..8d5cf63 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pManager.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pManager.java
@@ -1362,8 +1362,8 @@
public void setMiracastMode(int mode) {
try {
mService.setMiracastMode(mode);
- } catch(RemoteException e) {
- // ignore
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
}
}
@@ -1378,7 +1378,7 @@
try {
return mService.getMessenger();
} catch (RemoteException e) {
- return null;
+ throw e.rethrowFromSystemServer();
}
}
@@ -1393,7 +1393,7 @@
try {
return mService.getP2pStateMachineMessenger();
} catch (RemoteException e) {
- return null;
+ throw e.rethrowFromSystemServer();
}
}