diff options
286 files changed, 3930 insertions, 3213 deletions
diff --git a/api/system-current.txt b/api/system-current.txt index c81f4e9497cc..6db91c61ee4e 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -40610,6 +40610,7 @@ package android.telephony { method public boolean isSmsCapable(); method public boolean isTtyModeSupported(); method public boolean isVideoCallingEnabled(); + method public boolean isVisualVoicemailEnabled(android.telecom.PhoneAccountHandle); method public boolean isVoiceCapable(); method public boolean isVoicemailVibrationEnabled(android.telecom.PhoneAccountHandle); method public boolean isWorldPhone(); @@ -40623,6 +40624,7 @@ package android.telephony { method public boolean setPreferredNetworkTypeToGlobal(); method public boolean setRadio(boolean); method public boolean setRadioPower(boolean); + method public void setVisualVoicemailEnabled(android.telecom.PhoneAccountHandle, boolean); method public boolean setVoiceMailNumber(java.lang.String, java.lang.String); method public void silenceRinger(); method public boolean supplyPin(java.lang.String); diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp index 54c3d1a8d563..beb550cef476 100644 --- a/cmds/bootanimation/BootAnimation.cpp +++ b/cmds/bootanimation/BootAnimation.cpp @@ -77,12 +77,23 @@ static const long long ACCURATE_TIME_EPOCH = 946684800000; static const char EXIT_PROP_NAME[] = "service.bootanim.exit"; static const char PLAY_SOUND_PROP_NAME[] = "persist.sys.bootanim.play_sound"; static const int ANIM_ENTRY_NAME_MAX = 256; +static const char BOOT_COMPLETED_PROP_NAME[] = "sys.boot_completed"; +static const char BOOTREASON_PROP_NAME[] = "ro.boot.bootreason"; +// bootreasons list in "system/core/bootstat/bootstat.cpp". +static const std::vector<std::string> PLAY_SOUND_BOOTREASON_BLACKLIST { + "kernel_panic", + "Panic", + "Watchdog", +}; // --------------------------------------------------------------------------- BootAnimation::BootAnimation() : Thread(false), mClockEnabled(true), mTimeIsAccurate(false), mTimeCheckThread(NULL) { mSession = new SurfaceComposerClient(); + + // If the system has already booted, the animation is not being used for a boot. + mSystemBoot = !property_get_bool(BOOT_COMPLETED_PROP_NAME, 0); } BootAnimation::~BootAnimation() {} @@ -776,13 +787,9 @@ bool BootAnimation::playAnimation(const Animation& animation) break; // only play audio file the first time we animate the part - if (r == 0 && part.audioData) { - // Read the system property to see if we should play the sound. - // If not present, default to playing it. - if (property_get_bool(PLAY_SOUND_PROP_NAME, 1)) { - ALOGD("playing clip for part%d, size=%d", (int) i, part.audioLength); - audioplay::playClip(part.audioData, part.audioLength); - } + if (r == 0 && part.audioData && playSoundsAllowed()) { + ALOGD("playing clip for part%d, size=%d", (int) i, part.audioLength); + audioplay::playClip(part.audioData, part.audioLength); } glClearColor( @@ -918,6 +925,30 @@ BootAnimation::Animation* BootAnimation::loadAnimation(const String8& fn) return animation; } +bool BootAnimation::playSoundsAllowed() const { + // Only play sounds for system boots, not runtime restarts. + if (!mSystemBoot) { + return false; + } + + // Read the system property to see if we should play the sound. + // If it's not present, default to allowed. + if (!property_get_bool(PLAY_SOUND_PROP_NAME, 1)) { + return false; + } + + // Don't play sounds if this is a reboot due to an error. + char bootreason[PROPERTY_VALUE_MAX]; + if (property_get(BOOTREASON_PROP_NAME, bootreason, nullptr) > 0) { + for (const auto& str : PLAY_SOUND_BOOTREASON_BLACKLIST) { + if (strcasecmp(str.c_str(), bootreason) == 0) { + return false; + } + } + } + return true; +} + bool BootAnimation::updateIsTimeAccurate() { static constexpr long long MAX_TIME_IN_PAST = 60000LL * 60LL * 24LL * 30LL; // 30 days static constexpr long long MAX_TIME_IN_FUTURE = 60000LL * 90LL; // 90 minutes diff --git a/cmds/bootanimation/BootAnimation.h b/cmds/bootanimation/BootAnimation.h index a53216eb0310..fd497a362fc7 100644 --- a/cmds/bootanimation/BootAnimation.h +++ b/cmds/bootanimation/BootAnimation.h @@ -120,6 +120,7 @@ private: void releaseAnimation(Animation*) const; bool parseAnimationDesc(Animation&); bool preloadZip(Animation &animation); + bool playSoundsAllowed() const; void checkExit(); @@ -137,6 +138,7 @@ private: sp<Surface> mFlingerSurface; bool mClockEnabled; bool mTimeIsAccurate; + bool mSystemBoot; String8 mZipFileName; SortedVector<String8> mLoadedFiles; sp<TimeCheckThread> mTimeCheckThread; diff --git a/cmds/svc/src/com/android/commands/svc/WifiCommand.java b/cmds/svc/src/com/android/commands/svc/WifiCommand.java index 94214ff9694f..633dd9787cb1 100644 --- a/cmds/svc/src/com/android/commands/svc/WifiCommand.java +++ b/cmds/svc/src/com/android/commands/svc/WifiCommand.java @@ -52,7 +52,7 @@ public class WifiCommand extends Svc.Command { IWifiManager wifiMgr = IWifiManager.Stub.asInterface(ServiceManager.getService(Context.WIFI_SERVICE)); try { - wifiMgr.setWifiEnabled(flag); + wifiMgr.setWifiEnabled("com.android.shell", flag); } catch (RemoteException e) { System.err.println("Wi-Fi operation failed: " + e); diff --git a/core/java/android/accessibilityservice/AccessibilityService.java b/core/java/android/accessibilityservice/AccessibilityService.java index ae78e21807e8..c4eaccc1b406 100644 --- a/core/java/android/accessibilityservice/AccessibilityService.java +++ b/core/java/android/accessibilityservice/AccessibilityService.java @@ -628,8 +628,8 @@ public abstract class AccessibilityService extends Service { if (connection == null) { return false; } - List<MotionEvent> events = MotionEventGenerator.getMotionEventsFromGestureDescription( - gesture, 100); + List<GestureDescription.GestureStep> steps = + MotionEventGenerator.getGestureStepsFromGestureDescription(gesture, 100); try { synchronized (mLock) { mGestureStatusCallbackSequence++; @@ -641,8 +641,8 @@ public abstract class AccessibilityService extends Service { callback, handler); mGestureStatusCallbackInfos.put(mGestureStatusCallbackSequence, callbackInfo); } - connection.sendMotionEvents(mGestureStatusCallbackSequence, - new ParceledListSlice<>(events)); + connection.sendGesture(mGestureStatusCallbackSequence, + new ParceledListSlice<>(steps)); } } catch (RemoteException re) { throw new RuntimeException(re); diff --git a/core/java/android/accessibilityservice/GestureDescription.java b/core/java/android/accessibilityservice/GestureDescription.java index fc9581e7367c..d9b03faa42fa 100644 --- a/core/java/android/accessibilityservice/GestureDescription.java +++ b/core/java/android/accessibilityservice/GestureDescription.java @@ -21,6 +21,8 @@ import android.annotation.NonNull; import android.graphics.Path; import android.graphics.PathMeasure; import android.graphics.RectF; +import android.os.Parcel; +import android.os.Parcelable; import android.view.InputDevice; import android.view.MotionEvent; import android.view.MotionEvent.PointerCoords; @@ -303,13 +305,37 @@ public final class GestureDescription { } } - private static class TouchPoint { + /** + * The location of a finger for gesture dispatch + * + * @hide + */ + public static class TouchPoint implements Parcelable { + private static final int FLAG_IS_START_OF_PATH = 0x01; + private static final int FLAG_IS_END_OF_PATH = 0x02; + int mPathIndex; boolean mIsStartOfPath; boolean mIsEndOfPath; float mX; float mY; + public TouchPoint() { + } + + public TouchPoint(TouchPoint pointToCopy) { + copyFrom(pointToCopy); + } + + public TouchPoint(Parcel parcel) { + mPathIndex = parcel.readInt(); + int startEnd = parcel.readInt(); + mIsStartOfPath = (startEnd & FLAG_IS_START_OF_PATH) != 0; + mIsEndOfPath = (startEnd & FLAG_IS_END_OF_PATH) != 0; + mX = parcel.readFloat(); + mY = parcel.readFloat(); + } + void copyFrom(TouchPoint other) { mPathIndex = other.mPathIndex; mIsStartOfPath = other.mIsStartOfPath; @@ -317,12 +343,94 @@ public final class GestureDescription { mX = other.mX; mY = other.mY; } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeInt(mPathIndex); + int startEnd = mIsStartOfPath ? FLAG_IS_START_OF_PATH : 0; + startEnd |= mIsEndOfPath ? FLAG_IS_END_OF_PATH : 0; + dest.writeInt(startEnd); + dest.writeFloat(mX); + dest.writeFloat(mY); + } + + public static final Parcelable.Creator<TouchPoint> CREATOR + = new Parcelable.Creator<TouchPoint>() { + public TouchPoint createFromParcel(Parcel in) { + return new TouchPoint(in); + } + + public TouchPoint[] newArray(int size) { + return new TouchPoint[size]; + } + }; + } + + /** + * A step along a gesture. Contains all of the touch points at a particular time + * + * @hide + */ + public static class GestureStep implements Parcelable { + public long timeSinceGestureStart; + public int numTouchPoints; + public TouchPoint[] touchPoints; + + public GestureStep(long timeSinceGestureStart, int numTouchPoints, + TouchPoint[] touchPointsToCopy) { + this.timeSinceGestureStart = timeSinceGestureStart; + this.numTouchPoints = numTouchPoints; + this.touchPoints = new TouchPoint[numTouchPoints]; + for (int i = 0; i < numTouchPoints; i++) { + this.touchPoints[i] = new TouchPoint(touchPointsToCopy[i]); + } + } + + public GestureStep(Parcel parcel) { + timeSinceGestureStart = parcel.readLong(); + Parcelable[] parcelables = + parcel.readParcelableArray(TouchPoint.class.getClassLoader()); + numTouchPoints = (parcelables == null) ? 0 : parcelables.length; + touchPoints = new TouchPoint[numTouchPoints]; + for (int i = 0; i < numTouchPoints; i++) { + touchPoints[i] = (TouchPoint) parcelables[i]; + } + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeLong(timeSinceGestureStart); + dest.writeParcelableArray(touchPoints, flags); + } + + public static final Parcelable.Creator<GestureStep> CREATOR + = new Parcelable.Creator<GestureStep>() { + public GestureStep createFromParcel(Parcel in) { + return new GestureStep(in); + } + + public GestureStep[] newArray(int size) { + return new GestureStep[size]; + } + }; } /** * Class to convert a GestureDescription to a series of MotionEvents. + * + * @hide */ - static class MotionEventGenerator { + public static class MotionEventGenerator { /** * Constants used to initialize all MotionEvents */ @@ -341,38 +449,52 @@ public final class GestureDescription { private static PointerCoords[] sPointerCoords; private static PointerProperties[] sPointerProps; - static List<MotionEvent> getMotionEventsFromGestureDescription( + static List<GestureStep> getGestureStepsFromGestureDescription( GestureDescription description, int sampleTimeMs) { - final List<MotionEvent> motionEvents = new ArrayList<>(); + final List<GestureStep> gestureSteps = new ArrayList<>(); // Point data at each time we generate an event for final TouchPoint[] currentTouchPoints = getCurrentTouchPoints(description.getStrokeCount()); - // Point data sent in last touch event - int lastTouchPointSize = 0; - final TouchPoint[] lastTouchPoints = - getLastTouchPoints(description.getStrokeCount()); - + int currentTouchPointSize = 0; /* Loop through each time slice where there are touch points */ long timeSinceGestureStart = 0; long nextKeyPointTime = description.getNextKeyPointAtLeast(timeSinceGestureStart); while (nextKeyPointTime >= 0) { - timeSinceGestureStart = (lastTouchPointSize == 0) ? nextKeyPointTime + timeSinceGestureStart = (currentTouchPointSize == 0) ? nextKeyPointTime : Math.min(nextKeyPointTime, timeSinceGestureStart + sampleTimeMs); - int currentTouchPointSize = description.getPointsForTime(timeSinceGestureStart, + currentTouchPointSize = description.getPointsForTime(timeSinceGestureStart, currentTouchPoints); + gestureSteps.add(new GestureStep(timeSinceGestureStart, currentTouchPointSize, + currentTouchPoints)); + + /* Move to next time slice */ + nextKeyPointTime = description.getNextKeyPointAtLeast(timeSinceGestureStart + 1); + } + return gestureSteps; + } + + public static List<MotionEvent> getMotionEventsFromGestureSteps(List<GestureStep> steps) { + final List<MotionEvent> motionEvents = new ArrayList<>(); + + // Number of points in last touch event + int lastTouchPointSize = 0; + TouchPoint[] lastTouchPoints; + + for (int i = 0; i < steps.size(); i++) { + GestureStep step = steps.get(i); + int currentTouchPointSize = step.numTouchPoints; + lastTouchPoints = getLastTouchPoints( + Math.max(lastTouchPointSize, currentTouchPointSize)); appendMoveEventIfNeeded(motionEvents, lastTouchPoints, lastTouchPointSize, - currentTouchPoints, currentTouchPointSize, timeSinceGestureStart); + step.touchPoints, currentTouchPointSize, step.timeSinceGestureStart); lastTouchPointSize = appendUpEvents(motionEvents, lastTouchPoints, - lastTouchPointSize, currentTouchPoints, currentTouchPointSize, - timeSinceGestureStart); + lastTouchPointSize, step.touchPoints, currentTouchPointSize, + step.timeSinceGestureStart); lastTouchPointSize = appendDownEvents(motionEvents, lastTouchPoints, - lastTouchPointSize, currentTouchPoints, currentTouchPointSize, - timeSinceGestureStart); - - /* Move to next time slice */ - nextKeyPointTime = description.getNextKeyPointAtLeast(timeSinceGestureStart + 1); + lastTouchPointSize, step.touchPoints, currentTouchPointSize, + step.timeSinceGestureStart); } return motionEvents; } diff --git a/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl b/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl index 7a55079d3ecf..81cddbac3f53 100644 --- a/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl +++ b/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl @@ -88,5 +88,5 @@ interface IAccessibilityServiceConnection { void setSoftKeyboardCallbackEnabled(boolean enabled); - void sendMotionEvents(int sequence, in ParceledListSlice events); + void sendGesture(int sequence, in ParceledListSlice gestureSteps); } diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index a4c667f90852..5f8350f72a54 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -66,6 +66,7 @@ import android.os.Looper; import android.os.Parcelable; import android.os.PersistableBundle; import android.os.RemoteException; +import android.os.ServiceManager.ServiceNotFoundException; import android.os.StrictMode; import android.os.SystemProperties; import android.os.UserHandle; @@ -5591,7 +5592,11 @@ public class Activity extends ContextThemeWrapper return; } - mSearchManager = new SearchManager(this, null); + try { + mSearchManager = new SearchManager(this, null); + } catch (ServiceNotFoundException e) { + throw new IllegalStateException(e); + } } @Override diff --git a/core/java/android/app/Fragment.java b/core/java/android/app/Fragment.java index d6529d6610ab..136728087d0f 100644 --- a/core/java/android/app/Fragment.java +++ b/core/java/android/app/Fragment.java @@ -1485,7 +1485,7 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene * * <p>If your app's <code>targetSdkVersion</code> is {@link android.os.Build.VERSION_CODES#M} * or lower, child fragments being restored from the savedInstanceState are restored after - * <code>onCreate</code> returns. When targeting @link android.os.Build.VERSION_CODES#N} or + * <code>onCreate</code> returns. When targeting {@link android.os.Build.VERSION_CODES#N} or * above and running on an N or newer platform version * they are restored by <code>Fragment.onCreate</code>.</p> * diff --git a/core/java/android/app/IWallpaperManager.aidl b/core/java/android/app/IWallpaperManager.aidl index db7d54bd40cf..ec22ff65a5f8 100644 --- a/core/java/android/app/IWallpaperManager.aidl +++ b/core/java/android/app/IWallpaperManager.aidl @@ -128,7 +128,7 @@ interface IWallpaperManager { /* * Backup: is the current system wallpaper image eligible for off-device backup? */ - boolean isWallpaperBackupEligible(int userId); + boolean isWallpaperBackupEligible(int which, int userId); /* * Keyguard: register a callback for being notified that lock-state relevant diff --git a/core/java/android/app/KeyguardManager.java b/core/java/android/app/KeyguardManager.java index 505e081bddb4..da99e8005f38 100644 --- a/core/java/android/app/KeyguardManager.java +++ b/core/java/android/app/KeyguardManager.java @@ -27,6 +27,7 @@ import android.os.RemoteException; import android.os.IBinder; import android.os.IUserManager; import android.os.ServiceManager; +import android.os.ServiceManager.ServiceNotFoundException; import android.os.UserHandle; import android.os.UserManager; import android.view.IWindowManager; @@ -192,12 +193,12 @@ public class KeyguardManager { } - KeyguardManager() { + KeyguardManager() throws ServiceNotFoundException { mWM = WindowManagerGlobal.getWindowManagerService(); mTrustManager = ITrustManager.Stub.asInterface( - ServiceManager.getService(Context.TRUST_SERVICE)); + ServiceManager.getServiceOrThrow(Context.TRUST_SERVICE)); mUserManager = IUserManager.Stub.asInterface( - ServiceManager.getService(Context.USER_SERVICE)); + ServiceManager.getServiceOrThrow(Context.USER_SERVICE)); } /** diff --git a/core/java/android/app/SearchManager.java b/core/java/android/app/SearchManager.java index ac4abf5c36a4..ee6a3acb6eee 100644 --- a/core/java/android/app/SearchManager.java +++ b/core/java/android/app/SearchManager.java @@ -31,6 +31,7 @@ import android.os.Bundle; import android.os.Handler; import android.os.RemoteException; import android.os.ServiceManager; +import android.os.ServiceManager.ServiceNotFoundException; import android.os.UserHandle; import android.text.TextUtils; import android.util.Log; @@ -536,7 +537,7 @@ public class SearchManager /** * Reference to the shared system search service. */ - private static ISearchManager mService; + private final ISearchManager mService; private final Context mContext; @@ -547,11 +548,11 @@ public class SearchManager private SearchDialog mSearchDialog; - /*package*/ SearchManager(Context context, Handler handler) { + /*package*/ SearchManager(Context context, Handler handler) throws ServiceNotFoundException { mContext = context; mHandler = handler; mService = ISearchManager.Stub.asInterface( - ServiceManager.getService(Context.SEARCH_SERVICE)); + ServiceManager.getServiceOrThrow(Context.SEARCH_SERVICE)); } /** @@ -620,7 +621,7 @@ public class SearchManager return; } - UiModeManager uiModeManager = new UiModeManager(); + final UiModeManager uiModeManager = mContext.getSystemService(UiModeManager.class); // Don't show search dialog on televisions. if (uiModeManager.getCurrentModeType() != Configuration.UI_MODE_TYPE_TELEVISION) { ensureSearchDialog(); diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java index 55744b935f51..1778ca77d1c5 100644 --- a/core/java/android/app/SystemServiceRegistry.java +++ b/core/java/android/app/SystemServiceRegistry.java @@ -16,14 +16,10 @@ package android.app; -import com.android.internal.app.IAppOpsService; -import com.android.internal.app.ISoundTriggerService; -import com.android.internal.appwidget.IAppWidgetService; -import com.android.internal.os.IDropBoxManagerService; - import android.accounts.AccountManager; import android.accounts.IAccountManager; import android.app.admin.DevicePolicyManager; +import android.app.admin.IDevicePolicyManager; import android.app.job.IJobScheduler; import android.app.job.JobScheduler; import android.app.trust.TrustManager; @@ -36,7 +32,6 @@ import android.content.ClipboardManager; import android.content.Context; import android.content.IRestrictionsManager; import android.content.RestrictionsManager; -import android.content.pm.ILauncherApps; import android.content.pm.IShortcutService; import android.content.pm.LauncherApps; import android.content.pm.ShortcutManager; @@ -48,13 +43,15 @@ import android.hardware.SerialManager; import android.hardware.SystemSensorManager; import android.hardware.camera2.CameraManager; import android.hardware.display.DisplayManager; +import android.hardware.fingerprint.FingerprintManager; +import android.hardware.fingerprint.IFingerprintService; import android.hardware.hdmi.HdmiControlManager; import android.hardware.hdmi.IHdmiControlService; import android.hardware.input.InputManager; import android.hardware.location.ContextHubManager; +import android.hardware.radio.RadioManager; import android.hardware.usb.IUsbManager; import android.hardware.usb.UsbManager; -import android.hardware.radio.RadioManager; import android.location.CountryDetector; import android.location.ICountryDetector; import android.location.ILocationManager; @@ -90,8 +87,10 @@ import android.net.wifi.p2p.IWifiP2pManager; import android.net.wifi.p2p.WifiP2pManager; import android.nfc.NfcManager; import android.os.BatteryManager; +import android.os.BatteryStats; import android.os.DropBoxManager; import android.os.HardwarePropertiesManager; +import android.os.IBatteryPropertiesRegistrar; import android.os.IBinder; import android.os.IHardwarePropertiesManager; import android.os.IPowerManager; @@ -101,6 +100,7 @@ import android.os.PowerManager; import android.os.Process; import android.os.RecoverySystem; import android.os.ServiceManager; +import android.os.ServiceManager.ServiceNotFoundException; import android.os.SystemVibrator; import android.os.UserHandle; import android.os.UserManager; @@ -109,8 +109,6 @@ import android.os.health.SystemHealthManager; import android.os.storage.StorageManager; import android.print.IPrintManager; import android.print.PrintManager; -import android.hardware.fingerprint.FingerprintManager; -import android.hardware.fingerprint.IFingerprintService; import android.service.persistentdata.IPersistentDataBlockService; import android.service.persistentdata.PersistentDataBlockManager; import android.telecom.TelecomManager; @@ -120,7 +118,6 @@ import android.telephony.TelephonyManager; import android.util.Log; import android.view.ContextThemeWrapper; import android.view.LayoutInflater; -import com.android.internal.policy.PhoneLayoutInflater; import android.view.WindowManager; import android.view.WindowManagerImpl; import android.view.accessibility.AccessibilityManager; @@ -128,6 +125,13 @@ import android.view.accessibility.CaptioningManager; import android.view.inputmethod.InputMethodManager; import android.view.textservice.TextServicesManager; +import com.android.internal.app.IAppOpsService; +import com.android.internal.app.IBatteryStats; +import com.android.internal.app.ISoundTriggerService; +import com.android.internal.appwidget.IAppWidgetService; +import com.android.internal.os.IDropBoxManagerService; +import com.android.internal.policy.PhoneLayoutInflater; + import java.util.HashMap; /** @@ -135,7 +139,7 @@ import java.util.HashMap; * Used by {@link ContextImpl}. */ final class SystemServiceRegistry { - private final static String TAG = "SystemServiceRegistry"; + private static final String TAG = "SystemServiceRegistry"; // Service registry information. // This information is never changed once static initialization has completed. @@ -166,8 +170,8 @@ final class SystemServiceRegistry { registerService(Context.ACCOUNT_SERVICE, AccountManager.class, new CachedServiceFetcher<AccountManager>() { @Override - public AccountManager createService(ContextImpl ctx) { - IBinder b = ServiceManager.getService(Context.ACCOUNT_SERVICE); + public AccountManager createService(ContextImpl ctx) throws ServiceNotFoundException { + IBinder b = ServiceManager.getServiceOrThrow(Context.ACCOUNT_SERVICE); IAccountManager service = IAccountManager.Stub.asInterface(b); return new AccountManager(ctx, service); }}); @@ -182,8 +186,8 @@ final class SystemServiceRegistry { registerService(Context.ALARM_SERVICE, AlarmManager.class, new CachedServiceFetcher<AlarmManager>() { @Override - public AlarmManager createService(ContextImpl ctx) { - IBinder b = ServiceManager.getService(Context.ALARM_SERVICE); + public AlarmManager createService(ContextImpl ctx) throws ServiceNotFoundException { + IBinder b = ServiceManager.getServiceOrThrow(Context.ALARM_SERVICE); IAlarmManager service = IAlarmManager.Stub.asInterface(b); return new AlarmManager(service, ctx); }}); @@ -212,15 +216,15 @@ final class SystemServiceRegistry { registerService(Context.HDMI_CONTROL_SERVICE, HdmiControlManager.class, new StaticServiceFetcher<HdmiControlManager>() { @Override - public HdmiControlManager createService() { - IBinder b = ServiceManager.getService(Context.HDMI_CONTROL_SERVICE); + public HdmiControlManager createService() throws ServiceNotFoundException { + IBinder b = ServiceManager.getServiceOrThrow(Context.HDMI_CONTROL_SERVICE); return new HdmiControlManager(IHdmiControlService.Stub.asInterface(b)); }}); registerService(Context.CLIPBOARD_SERVICE, ClipboardManager.class, new CachedServiceFetcher<ClipboardManager>() { @Override - public ClipboardManager createService(ContextImpl ctx) { + public ClipboardManager createService(ContextImpl ctx) throws ServiceNotFoundException { return new ClipboardManager(ctx.getOuterContext(), ctx.mMainThread.getHandler()); }}); @@ -233,8 +237,8 @@ final class SystemServiceRegistry { registerService(Context.CONNECTIVITY_SERVICE, ConnectivityManager.class, new StaticApplicationContextServiceFetcher<ConnectivityManager>() { @Override - public ConnectivityManager createService(Context context) { - IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE); + public ConnectivityManager createService(Context context) throws ServiceNotFoundException { + IBinder b = ServiceManager.getServiceOrThrow(Context.CONNECTIVITY_SERVICE); IConnectivityManager service = IConnectivityManager.Stub.asInterface(b); return new ConnectivityManager(context, service); }}); @@ -242,16 +246,17 @@ final class SystemServiceRegistry { registerService(Context.COUNTRY_DETECTOR, CountryDetector.class, new StaticServiceFetcher<CountryDetector>() { @Override - public CountryDetector createService() { - IBinder b = ServiceManager.getService(Context.COUNTRY_DETECTOR); + public CountryDetector createService() throws ServiceNotFoundException { + IBinder b = ServiceManager.getServiceOrThrow(Context.COUNTRY_DETECTOR); return new CountryDetector(ICountryDetector.Stub.asInterface(b)); }}); registerService(Context.DEVICE_POLICY_SERVICE, DevicePolicyManager.class, new CachedServiceFetcher<DevicePolicyManager>() { @Override - public DevicePolicyManager createService(ContextImpl ctx) { - return DevicePolicyManager.create(ctx); + public DevicePolicyManager createService(ContextImpl ctx) throws ServiceNotFoundException { + IBinder b = ServiceManager.getServiceOrThrow(Context.DEVICE_POLICY_SERVICE); + return new DevicePolicyManager(ctx, IDevicePolicyManager.Stub.asInterface(b)); }}); registerService(Context.DOWNLOAD_SERVICE, DownloadManager.class, @@ -264,8 +269,12 @@ final class SystemServiceRegistry { registerService(Context.BATTERY_SERVICE, BatteryManager.class, new StaticServiceFetcher<BatteryManager>() { @Override - public BatteryManager createService() { - return new BatteryManager(); + public BatteryManager createService() throws ServiceNotFoundException { + IBatteryStats stats = IBatteryStats.Stub.asInterface( + ServiceManager.getServiceOrThrow(BatteryStats.SERVICE_NAME)); + IBatteryPropertiesRegistrar registrar = IBatteryPropertiesRegistrar.Stub + .asInterface(ServiceManager.getServiceOrThrow("batteryproperties")); + return new BatteryManager(stats, registrar); }}); registerService(Context.NFC_SERVICE, NfcManager.class, @@ -278,16 +287,9 @@ final class SystemServiceRegistry { registerService(Context.DROPBOX_SERVICE, DropBoxManager.class, new CachedServiceFetcher<DropBoxManager>() { @Override - public DropBoxManager createService(ContextImpl ctx) { - IBinder b = ServiceManager.getService(Context.DROPBOX_SERVICE); + public DropBoxManager createService(ContextImpl ctx) throws ServiceNotFoundException { + IBinder b = ServiceManager.getServiceOrThrow(Context.DROPBOX_SERVICE); IDropBoxManagerService service = IDropBoxManagerService.Stub.asInterface(b); - if (service == null) { - // Don't return a DropBoxManager that will NPE upon use. - // This also avoids caching a broken DropBoxManager in - // getDropBoxManager during early boot, before the - // DROPBOX_SERVICE is registered. - return null; - } return new DropBoxManager(ctx, service); }}); @@ -322,7 +324,7 @@ final class SystemServiceRegistry { registerService(Context.KEYGUARD_SERVICE, KeyguardManager.class, new StaticServiceFetcher<KeyguardManager>() { @Override - public KeyguardManager createService() { + public KeyguardManager createService() throws ServiceNotFoundException { return new KeyguardManager(); }}); @@ -336,17 +338,17 @@ final class SystemServiceRegistry { registerService(Context.LOCATION_SERVICE, LocationManager.class, new CachedServiceFetcher<LocationManager>() { @Override - public LocationManager createService(ContextImpl ctx) { - IBinder b = ServiceManager.getService(Context.LOCATION_SERVICE); + public LocationManager createService(ContextImpl ctx) throws ServiceNotFoundException { + IBinder b = ServiceManager.getServiceOrThrow(Context.LOCATION_SERVICE); return new LocationManager(ctx, ILocationManager.Stub.asInterface(b)); }}); registerService(Context.NETWORK_POLICY_SERVICE, NetworkPolicyManager.class, new CachedServiceFetcher<NetworkPolicyManager>() { @Override - public NetworkPolicyManager createService(ContextImpl ctx) { + public NetworkPolicyManager createService(ContextImpl ctx) throws ServiceNotFoundException { return new NetworkPolicyManager(ctx, INetworkPolicyManager.Stub.asInterface( - ServiceManager.getService(Context.NETWORK_POLICY_SERVICE))); + ServiceManager.getServiceOrThrow(Context.NETWORK_POLICY_SERVICE))); }}); registerService(Context.NOTIFICATION_SERVICE, NotificationManager.class, @@ -368,8 +370,8 @@ final class SystemServiceRegistry { registerService(Context.NSD_SERVICE, NsdManager.class, new CachedServiceFetcher<NsdManager>() { @Override - public NsdManager createService(ContextImpl ctx) { - IBinder b = ServiceManager.getService(Context.NSD_SERVICE); + public NsdManager createService(ContextImpl ctx) throws ServiceNotFoundException { + IBinder b = ServiceManager.getServiceOrThrow(Context.NSD_SERVICE); INsdManager service = INsdManager.Stub.asInterface(b); return new NsdManager(ctx.getOuterContext(), service); }}); @@ -377,12 +379,9 @@ final class SystemServiceRegistry { registerService(Context.POWER_SERVICE, PowerManager.class, new CachedServiceFetcher<PowerManager>() { @Override - public PowerManager createService(ContextImpl ctx) { - IBinder b = ServiceManager.getService(Context.POWER_SERVICE); + public PowerManager createService(ContextImpl ctx) throws ServiceNotFoundException { + IBinder b = ServiceManager.getServiceOrThrow(Context.POWER_SERVICE); IPowerManager service = IPowerManager.Stub.asInterface(b); - if (service == null) { - Log.wtf(TAG, "Failed to get power manager service."); - } return new PowerManager(ctx.getOuterContext(), service, ctx.mMainThread.getHandler()); }}); @@ -390,19 +389,16 @@ final class SystemServiceRegistry { registerService(Context.RECOVERY_SERVICE, RecoverySystem.class, new CachedServiceFetcher<RecoverySystem>() { @Override - public RecoverySystem createService(ContextImpl ctx) { - IBinder b = ServiceManager.getService(Context.RECOVERY_SERVICE); + public RecoverySystem createService(ContextImpl ctx) throws ServiceNotFoundException { + IBinder b = ServiceManager.getServiceOrThrow(Context.RECOVERY_SERVICE); IRecoverySystem service = IRecoverySystem.Stub.asInterface(b); - if (service == null) { - Log.wtf(TAG, "Failed to get recovery service."); - } return new RecoverySystem(service); }}); registerService(Context.SEARCH_SERVICE, SearchManager.class, new CachedServiceFetcher<SearchManager>() { @Override - public SearchManager createService(ContextImpl ctx) { + public SearchManager createService(ContextImpl ctx) throws ServiceNotFoundException { return new SearchManager(ctx.getOuterContext(), ctx.mMainThread.getHandler()); }}); @@ -425,7 +421,7 @@ final class SystemServiceRegistry { registerService(Context.STORAGE_SERVICE, StorageManager.class, new CachedServiceFetcher<StorageManager>() { @Override - public StorageManager createService(ContextImpl ctx) { + public StorageManager createService(ContextImpl ctx) throws ServiceNotFoundException { return new StorageManager(ctx, ctx.mMainThread.getHandler().getLooper()); }}); @@ -460,23 +456,23 @@ final class SystemServiceRegistry { registerService(Context.UI_MODE_SERVICE, UiModeManager.class, new CachedServiceFetcher<UiModeManager>() { @Override - public UiModeManager createService(ContextImpl ctx) { + public UiModeManager createService(ContextImpl ctx) throws ServiceNotFoundException { return new UiModeManager(); }}); registerService(Context.USB_SERVICE, UsbManager.class, new CachedServiceFetcher<UsbManager>() { @Override - public UsbManager createService(ContextImpl ctx) { - IBinder b = ServiceManager.getService(Context.USB_SERVICE); + public UsbManager createService(ContextImpl ctx) throws ServiceNotFoundException { + IBinder b = ServiceManager.getServiceOrThrow(Context.USB_SERVICE); return new UsbManager(ctx, IUsbManager.Stub.asInterface(b)); }}); registerService(Context.SERIAL_SERVICE, SerialManager.class, new CachedServiceFetcher<SerialManager>() { @Override - public SerialManager createService(ContextImpl ctx) { - IBinder b = ServiceManager.getService(Context.SERIAL_SERVICE); + public SerialManager createService(ContextImpl ctx) throws ServiceNotFoundException { + IBinder b = ServiceManager.getServiceOrThrow(Context.SERIAL_SERVICE); return new SerialManager(ctx, ISerialManager.Stub.asInterface(b)); }}); @@ -498,8 +494,8 @@ final class SystemServiceRegistry { registerService(Context.WIFI_SERVICE, WifiManager.class, new CachedServiceFetcher<WifiManager>() { @Override - public WifiManager createService(ContextImpl ctx) { - IBinder b = ServiceManager.getService(Context.WIFI_SERVICE); + public WifiManager createService(ContextImpl ctx) throws ServiceNotFoundException { + IBinder b = ServiceManager.getServiceOrThrow(Context.WIFI_SERVICE); IWifiManager service = IWifiManager.Stub.asInterface(b); return new WifiManager(ctx.getOuterContext(), service, ConnectivityThread.getInstanceLooper()); @@ -508,8 +504,8 @@ final class SystemServiceRegistry { registerService(Context.WIFI_P2P_SERVICE, WifiP2pManager.class, new StaticServiceFetcher<WifiP2pManager>() { @Override - public WifiP2pManager createService() { - IBinder b = ServiceManager.getService(Context.WIFI_P2P_SERVICE); + public WifiP2pManager createService() throws ServiceNotFoundException { + IBinder b = ServiceManager.getServiceOrThrow(Context.WIFI_P2P_SERVICE); IWifiP2pManager service = IWifiP2pManager.Stub.asInterface(b); return new WifiP2pManager(service); }}); @@ -517,20 +513,17 @@ final class SystemServiceRegistry { registerService(Context.WIFI_NAN_SERVICE, WifiNanManager.class, new StaticServiceFetcher<WifiNanManager>() { @Override - public WifiNanManager createService() { - IBinder b = ServiceManager.getService(Context.WIFI_NAN_SERVICE); + public WifiNanManager createService() throws ServiceNotFoundException { + IBinder b = ServiceManager.getServiceOrThrow(Context.WIFI_NAN_SERVICE); IWifiNanManager service = IWifiNanManager.Stub.asInterface(b); - if (service == null) { - return null; - } return new WifiNanManager(service); }}); registerService(Context.WIFI_SCANNING_SERVICE, WifiScanner.class, new CachedServiceFetcher<WifiScanner>() { @Override - public WifiScanner createService(ContextImpl ctx) { - IBinder b = ServiceManager.getService(Context.WIFI_SCANNING_SERVICE); + public WifiScanner createService(ContextImpl ctx) throws ServiceNotFoundException { + IBinder b = ServiceManager.getServiceOrThrow(Context.WIFI_SCANNING_SERVICE); IWifiScanner service = IWifiScanner.Stub.asInterface(b); return new WifiScanner(ctx.getOuterContext(), service, ConnectivityThread.getInstanceLooper()); @@ -539,8 +532,8 @@ final class SystemServiceRegistry { registerService(Context.WIFI_RTT_SERVICE, RttManager.class, new CachedServiceFetcher<RttManager>() { @Override - public RttManager createService(ContextImpl ctx) { - IBinder b = ServiceManager.getService(Context.WIFI_RTT_SERVICE); + public RttManager createService(ContextImpl ctx) throws ServiceNotFoundException { + IBinder b = ServiceManager.getServiceOrThrow(Context.WIFI_RTT_SERVICE); IRttManager service = IRttManager.Stub.asInterface(b); return new RttManager(ctx.getOuterContext(), service, ConnectivityThread.getInstanceLooper()); @@ -549,8 +542,8 @@ final class SystemServiceRegistry { registerService(Context.ETHERNET_SERVICE, EthernetManager.class, new CachedServiceFetcher<EthernetManager>() { @Override - public EthernetManager createService(ContextImpl ctx) { - IBinder b = ServiceManager.getService(Context.ETHERNET_SERVICE); + public EthernetManager createService(ContextImpl ctx) throws ServiceNotFoundException { + IBinder b = ServiceManager.getServiceOrThrow(Context.ETHERNET_SERVICE); IEthernetManager service = IEthernetManager.Stub.asInterface(b); return new EthernetManager(ctx.getOuterContext(), service); }}); @@ -565,8 +558,8 @@ final class SystemServiceRegistry { registerService(Context.USER_SERVICE, UserManager.class, new CachedServiceFetcher<UserManager>() { @Override - public UserManager createService(ContextImpl ctx) { - IBinder b = ServiceManager.getService(Context.USER_SERVICE); + public UserManager createService(ContextImpl ctx) throws ServiceNotFoundException { + IBinder b = ServiceManager.getServiceOrThrow(Context.USER_SERVICE); IUserManager service = IUserManager.Stub.asInterface(b); return new UserManager(ctx, service); }}); @@ -574,8 +567,8 @@ final class SystemServiceRegistry { registerService(Context.APP_OPS_SERVICE, AppOpsManager.class, new CachedServiceFetcher<AppOpsManager>() { @Override - public AppOpsManager createService(ContextImpl ctx) { - IBinder b = ServiceManager.getService(Context.APP_OPS_SERVICE); + public AppOpsManager createService(ContextImpl ctx) throws ServiceNotFoundException { + IBinder b = ServiceManager.getServiceOrThrow(Context.APP_OPS_SERVICE); IAppOpsService service = IAppOpsService.Stub.asInterface(b); return new AppOpsManager(ctx, service); }}); @@ -597,8 +590,8 @@ final class SystemServiceRegistry { registerService(Context.RESTRICTIONS_SERVICE, RestrictionsManager.class, new CachedServiceFetcher<RestrictionsManager>() { @Override - public RestrictionsManager createService(ContextImpl ctx) { - IBinder b = ServiceManager.getService(Context.RESTRICTIONS_SERVICE); + public RestrictionsManager createService(ContextImpl ctx) throws ServiceNotFoundException { + IBinder b = ServiceManager.getServiceOrThrow(Context.RESTRICTIONS_SERVICE); IRestrictionsManager service = IRestrictionsManager.Stub.asInterface(b); return new RestrictionsManager(ctx, service); }}); @@ -606,8 +599,8 @@ final class SystemServiceRegistry { registerService(Context.PRINT_SERVICE, PrintManager.class, new CachedServiceFetcher<PrintManager>() { @Override - public PrintManager createService(ContextImpl ctx) { - IBinder iBinder = ServiceManager.getService(Context.PRINT_SERVICE); + public PrintManager createService(ContextImpl ctx) throws ServiceNotFoundException { + IBinder iBinder = ServiceManager.getServiceOrThrow(Context.PRINT_SERVICE); IPrintManager service = IPrintManager.Stub.asInterface(iBinder); return new PrintManager(ctx.getOuterContext(), service, UserHandle.myUserId(), UserHandle.getAppId(Process.myUid())); @@ -616,7 +609,7 @@ final class SystemServiceRegistry { registerService(Context.CONSUMER_IR_SERVICE, ConsumerIrManager.class, new CachedServiceFetcher<ConsumerIrManager>() { @Override - public ConsumerIrManager createService(ContextImpl ctx) { + public ConsumerIrManager createService(ContextImpl ctx) throws ServiceNotFoundException { return new ConsumerIrManager(ctx); }}); @@ -630,16 +623,16 @@ final class SystemServiceRegistry { registerService(Context.TRUST_SERVICE, TrustManager.class, new StaticServiceFetcher<TrustManager>() { @Override - public TrustManager createService() { - IBinder b = ServiceManager.getService(Context.TRUST_SERVICE); + public TrustManager createService() throws ServiceNotFoundException { + IBinder b = ServiceManager.getServiceOrThrow(Context.TRUST_SERVICE); return new TrustManager(b); }}); registerService(Context.FINGERPRINT_SERVICE, FingerprintManager.class, new CachedServiceFetcher<FingerprintManager>() { @Override - public FingerprintManager createService(ContextImpl ctx) { - IBinder binder = ServiceManager.getService(Context.FINGERPRINT_SERVICE); + public FingerprintManager createService(ContextImpl ctx) throws ServiceNotFoundException { + IBinder binder = ServiceManager.getServiceOrThrow(Context.FINGERPRINT_SERVICE); IFingerprintService service = IFingerprintService.Stub.asInterface(binder); return new FingerprintManager(ctx.getOuterContext(), service); }}); @@ -647,8 +640,8 @@ final class SystemServiceRegistry { registerService(Context.TV_INPUT_SERVICE, TvInputManager.class, new StaticServiceFetcher<TvInputManager>() { @Override - public TvInputManager createService() { - IBinder iBinder = ServiceManager.getService(Context.TV_INPUT_SERVICE); + public TvInputManager createService() throws ServiceNotFoundException { + IBinder iBinder = ServiceManager.getServiceOrThrow(Context.TV_INPUT_SERVICE); ITvInputManager service = ITvInputManager.Stub.asInterface(iBinder); return new TvInputManager(service, UserHandle.myUserId()); }}); @@ -656,15 +649,15 @@ final class SystemServiceRegistry { registerService(Context.NETWORK_SCORE_SERVICE, NetworkScoreManager.class, new CachedServiceFetcher<NetworkScoreManager>() { @Override - public NetworkScoreManager createService(ContextImpl ctx) { + public NetworkScoreManager createService(ContextImpl ctx) throws ServiceNotFoundException { return new NetworkScoreManager(ctx); }}); registerService(Context.USAGE_STATS_SERVICE, UsageStatsManager.class, new CachedServiceFetcher<UsageStatsManager>() { @Override - public UsageStatsManager createService(ContextImpl ctx) { - IBinder iBinder = ServiceManager.getService(Context.USAGE_STATS_SERVICE); + public UsageStatsManager createService(ContextImpl ctx) throws ServiceNotFoundException { + IBinder iBinder = ServiceManager.getServiceOrThrow(Context.USAGE_STATS_SERVICE); IUsageStatsManager service = IUsageStatsManager.Stub.asInterface(iBinder); return new UsageStatsManager(ctx.getOuterContext(), service); }}); @@ -672,23 +665,23 @@ final class SystemServiceRegistry { registerService(Context.NETWORK_STATS_SERVICE, NetworkStatsManager.class, new CachedServiceFetcher<NetworkStatsManager>() { @Override - public NetworkStatsManager createService(ContextImpl ctx) { + public NetworkStatsManager createService(ContextImpl ctx) throws ServiceNotFoundException { return new NetworkStatsManager(ctx.getOuterContext()); }}); registerService(Context.JOB_SCHEDULER_SERVICE, JobScheduler.class, new StaticServiceFetcher<JobScheduler>() { @Override - public JobScheduler createService() { - IBinder b = ServiceManager.getService(Context.JOB_SCHEDULER_SERVICE); + public JobScheduler createService() throws ServiceNotFoundException { + IBinder b = ServiceManager.getServiceOrThrow(Context.JOB_SCHEDULER_SERVICE); return new JobSchedulerImpl(IJobScheduler.Stub.asInterface(b)); }}); registerService(Context.PERSISTENT_DATA_BLOCK_SERVICE, PersistentDataBlockManager.class, new StaticServiceFetcher<PersistentDataBlockManager>() { @Override - public PersistentDataBlockManager createService() { - IBinder b = ServiceManager.getService(Context.PERSISTENT_DATA_BLOCK_SERVICE); + public PersistentDataBlockManager createService() throws ServiceNotFoundException { + IBinder b = ServiceManager.getServiceOrThrow(Context.PERSISTENT_DATA_BLOCK_SERVICE); IPersistentDataBlockService persistentDataBlockService = IPersistentDataBlockService.Stub.asInterface(b); if (persistentDataBlockService != null) { @@ -709,19 +702,16 @@ final class SystemServiceRegistry { registerService(Context.APPWIDGET_SERVICE, AppWidgetManager.class, new CachedServiceFetcher<AppWidgetManager>() { @Override - public AppWidgetManager createService(ContextImpl ctx) { - IBinder b = ServiceManager.getService(Context.APPWIDGET_SERVICE); + public AppWidgetManager createService(ContextImpl ctx) throws ServiceNotFoundException { + IBinder b = ServiceManager.getServiceOrThrow(Context.APPWIDGET_SERVICE); return new AppWidgetManager(ctx, IAppWidgetService.Stub.asInterface(b)); }}); registerService(Context.MIDI_SERVICE, MidiManager.class, new CachedServiceFetcher<MidiManager>() { @Override - public MidiManager createService(ContextImpl ctx) { - IBinder b = ServiceManager.getService(Context.MIDI_SERVICE); - if (b == null) { - return null; - } + public MidiManager createService(ContextImpl ctx) throws ServiceNotFoundException { + IBinder b = ServiceManager.getServiceOrThrow(Context.MIDI_SERVICE); return new MidiManager(IMidiManager.Stub.asInterface(b)); }}); @@ -735,43 +725,41 @@ final class SystemServiceRegistry { registerService(Context.HARDWARE_PROPERTIES_SERVICE, HardwarePropertiesManager.class, new CachedServiceFetcher<HardwarePropertiesManager>() { @Override - public HardwarePropertiesManager createService(ContextImpl ctx) { - IBinder b = ServiceManager.getService(Context.HARDWARE_PROPERTIES_SERVICE); - IHardwarePropertiesManager service = - IHardwarePropertiesManager.Stub.asInterface(b); - if (service == null) { - Log.wtf(TAG, "Failed to get hardwareproperties service."); - return null; - } - return new HardwarePropertiesManager(ctx, service); + public HardwarePropertiesManager createService(ContextImpl ctx) throws ServiceNotFoundException { + IBinder b = ServiceManager.getServiceOrThrow(Context.HARDWARE_PROPERTIES_SERVICE); + IHardwarePropertiesManager service = + IHardwarePropertiesManager.Stub.asInterface(b); + return new HardwarePropertiesManager(ctx, service); }}); registerService(Context.SOUND_TRIGGER_SERVICE, SoundTriggerManager.class, new CachedServiceFetcher<SoundTriggerManager>() { @Override - public SoundTriggerManager createService(ContextImpl ctx) { - IBinder b = ServiceManager.getService(Context.SOUND_TRIGGER_SERVICE); + public SoundTriggerManager createService(ContextImpl ctx) throws ServiceNotFoundException { + IBinder b = ServiceManager.getServiceOrThrow(Context.SOUND_TRIGGER_SERVICE); return new SoundTriggerManager(ctx, ISoundTriggerService.Stub.asInterface(b)); }}); registerService(Context.SHORTCUT_SERVICE, ShortcutManager.class, new CachedServiceFetcher<ShortcutManager>() { @Override - public ShortcutManager createService(ContextImpl ctx) { - return new ShortcutManager(ctx); + public ShortcutManager createService(ContextImpl ctx) throws ServiceNotFoundException { + IBinder b = ServiceManager.getServiceOrThrow(Context.SHORTCUT_SERVICE); + return new ShortcutManager(ctx, IShortcutService.Stub.asInterface(b)); }}); registerService(Context.SYSTEM_HEALTH_SERVICE, SystemHealthManager.class, new CachedServiceFetcher<SystemHealthManager>() { @Override - public SystemHealthManager createService(ContextImpl ctx) { - return new SystemHealthManager(); + public SystemHealthManager createService(ContextImpl ctx) throws ServiceNotFoundException { + IBinder b = ServiceManager.getServiceOrThrow(BatteryStats.SERVICE_NAME); + return new SystemHealthManager(IBatteryStats.Stub.asInterface(b)); }}); registerService(Context.CONTEXTHUB_SERVICE, ContextHubManager.class, new CachedServiceFetcher<ContextHubManager>() { @Override - public ContextHubManager createService(ContextImpl ctx) { + public ContextHubManager createService(ContextImpl ctx) throws ServiceNotFoundException { return new ContextHubManager(ctx.getOuterContext(), ctx.mMainThread.getHandler().getLooper()); }}); @@ -836,14 +824,18 @@ final class SystemServiceRegistry { // Fetch or create the service. Object service = cache[mCacheIndex]; if (service == null) { - service = createService(ctx); - cache[mCacheIndex] = service; + try { + service = createService(ctx); + cache[mCacheIndex] = service; + } catch (ServiceNotFoundException e) { + Log.w(TAG, e.getMessage(), e); + } } return (T)service; } } - public abstract T createService(ContextImpl ctx); + public abstract T createService(ContextImpl ctx) throws ServiceNotFoundException; } /** @@ -857,13 +849,17 @@ final class SystemServiceRegistry { public final T getService(ContextImpl unused) { synchronized (StaticServiceFetcher.this) { if (mCachedInstance == null) { - mCachedInstance = createService(); + try { + mCachedInstance = createService(); + } catch (ServiceNotFoundException e) { + Log.w(TAG, e.getMessage(), e); + } } return mCachedInstance; } } - public abstract T createService(); + public abstract T createService() throws ServiceNotFoundException; } /** @@ -886,13 +882,16 @@ final class SystemServiceRegistry { // it's the application context very early in app initialization. In both these // cases, the passed-in ContextImpl will not be freed, so it's safe to pass it // to the service. http://b/27532714 . - mCachedInstance = createService(appContext != null ? appContext : ctx); + try { + mCachedInstance = createService(appContext != null ? appContext : ctx); + } catch (ServiceNotFoundException e) { + Log.w(TAG, e.getMessage(), e); + } } return mCachedInstance; } } - public abstract T createService(Context applicationContext); + public abstract T createService(Context applicationContext) throws ServiceNotFoundException; } - } diff --git a/core/java/android/app/UiModeManager.java b/core/java/android/app/UiModeManager.java index 69e8df87384b..0046b0e4a8bf 100644 --- a/core/java/android/app/UiModeManager.java +++ b/core/java/android/app/UiModeManager.java @@ -22,6 +22,7 @@ import android.content.Context; import android.content.res.Configuration; import android.os.RemoteException; import android.os.ServiceManager; +import android.os.ServiceManager.ServiceNotFoundException; import android.util.Log; import java.lang.annotation.Retention; @@ -123,9 +124,9 @@ public class UiModeManager { private IUiModeManager mService; - /*package*/ UiModeManager() { + /*package*/ UiModeManager() throws ServiceNotFoundException { mService = IUiModeManager.Stub.asInterface( - ServiceManager.getService(Context.UI_MODE_SERVICE)); + ServiceManager.getServiceOrThrow(Context.UI_MODE_SERVICE)); } /** diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java index 20cbde176368..6e4466238af2 100644 --- a/core/java/android/app/WallpaperManager.java +++ b/core/java/android/app/WallpaperManager.java @@ -1680,13 +1680,13 @@ public class WallpaperManager { * Only the OS itself may use this method. * @hide */ - public boolean isWallpaperBackupEligible() { + public boolean isWallpaperBackupEligible(int which) { if (sGlobals.mService == null) { Log.w(TAG, "WallpaperService not running"); throw new RuntimeException(new DeadSystemException()); } try { - return sGlobals.mService.isWallpaperBackupEligible(mContext.getUserId()); + return sGlobals.mService.isWallpaperBackupEligible(which, mContext.getUserId()); } catch (RemoteException e) { Log.e(TAG, "Exception querying wallpaper backup eligibility: " + e.getMessage()); } diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index 3a2038fbc9de..6ac7132166f7 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -46,6 +46,7 @@ import android.os.RemoteException; import android.os.ServiceManager; import android.os.UserHandle; import android.os.UserManager; +import android.os.ServiceManager.ServiceNotFoundException; import android.provider.ContactsContract.Directory; import android.provider.Settings; import android.security.Credentials; @@ -99,28 +100,20 @@ public class DevicePolicyManager { private final IDevicePolicyManager mService; private final boolean mParentInstance; - private DevicePolicyManager(Context context, boolean parentInstance) { - this(context, - IDevicePolicyManager.Stub.asInterface( - ServiceManager.getService(Context.DEVICE_POLICY_SERVICE)), - parentInstance); + /** @hide */ + public DevicePolicyManager(Context context, IDevicePolicyManager service) { + this(context, service, false); } /** @hide */ @VisibleForTesting - protected DevicePolicyManager( - Context context, IDevicePolicyManager service, boolean parentInstance) { + protected DevicePolicyManager(Context context, IDevicePolicyManager service, + boolean parentInstance) { mContext = context; mService = service; mParentInstance = parentInstance; } - /** @hide */ - public static DevicePolicyManager create(Context context) { - DevicePolicyManager me = new DevicePolicyManager(context, false); - return me.mService != null ? me : null; - } - /** @hide test will override it. */ @VisibleForTesting protected int myUserId() { @@ -6054,7 +6047,7 @@ public class DevicePolicyManager { if (!mService.isManagedProfile(admin)) { throw new SecurityException("The current user does not have a parent profile."); } - return new DevicePolicyManager(mContext, true); + return new DevicePolicyManager(mContext, mService, true); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -6146,7 +6139,7 @@ public class DevicePolicyManager { throw new SecurityException("The user " + uInfo.id + " does not have a parent profile."); } - return new DevicePolicyManager(mContext, true); + return new DevicePolicyManager(mContext, mService, true); } /** diff --git a/core/java/android/app/usage/NetworkStatsManager.java b/core/java/android/app/usage/NetworkStatsManager.java index 7961a72a12e4..e805fabc7967 100644 --- a/core/java/android/app/usage/NetworkStatsManager.java +++ b/core/java/android/app/usage/NetworkStatsManager.java @@ -34,6 +34,7 @@ import android.os.Handler; import android.os.Looper; import android.os.RemoteException; import android.os.ServiceManager; +import android.os.ServiceManager.ServiceNotFoundException; import android.util.Log; /** @@ -95,10 +96,10 @@ public class NetworkStatsManager { /** * {@hide} */ - public NetworkStatsManager(Context context) { + public NetworkStatsManager(Context context) throws ServiceNotFoundException { mContext = context; mService = INetworkStatsService.Stub.asInterface( - ServiceManager.getService(Context.NETWORK_STATS_SERVICE)); + ServiceManager.getServiceOrThrow(Context.NETWORK_STATS_SERVICE)); } /** diff --git a/core/java/android/bluetooth/OobData.java b/core/java/android/bluetooth/OobData.java index 8e659e04d705..f53ca94a1d5c 100644 --- a/core/java/android/bluetooth/OobData.java +++ b/core/java/android/bluetooth/OobData.java @@ -31,6 +31,8 @@ import android.util.Log; */ public class OobData implements Parcelable { private byte[] securityManagerTk; + private byte[] leSecureConnectionsConfirmation; + private byte[] leSecureConnectionsRandom; public byte[] getSecurityManagerTk() { return securityManagerTk; @@ -45,10 +47,28 @@ public class OobData implements Parcelable { this.securityManagerTk = securityManagerTk; } + public byte[] getLeSecureConnectionsConfirmation() { + return leSecureConnectionsConfirmation; + } + + public void setLeSecureConnectionsConfirmation(byte[] leSecureConnectionsConfirmation) { + this.leSecureConnectionsConfirmation = leSecureConnectionsConfirmation; + } + + public byte[] getLeSecureConnectionsRandom() { + return leSecureConnectionsRandom; + } + + public void setLeSecureConnectionsRandom(byte[] leSecureConnectionsRandom) { + this.leSecureConnectionsRandom = leSecureConnectionsRandom; + } + public OobData() { } private OobData(Parcel in) { securityManagerTk = in.createByteArray(); + leSecureConnectionsConfirmation = in.createByteArray(); + leSecureConnectionsRandom = in.createByteArray(); } public int describeContents() { @@ -58,6 +78,8 @@ public class OobData implements Parcelable { @Override public void writeToParcel(Parcel out, int flags) { out.writeByteArray(securityManagerTk); + out.writeByteArray(leSecureConnectionsConfirmation); + out.writeByteArray(leSecureConnectionsRandom); } public static final Parcelable.Creator<OobData> CREATOR diff --git a/core/java/android/content/ClipboardManager.java b/core/java/android/content/ClipboardManager.java index 7244227584ee..c28172c6347c 100644 --- a/core/java/android/content/ClipboardManager.java +++ b/core/java/android/content/ClipboardManager.java @@ -16,12 +16,11 @@ package android.content; -import android.content.Context; +import android.os.Handler; import android.os.Message; import android.os.RemoteException; -import android.os.Handler; -import android.os.IBinder; import android.os.ServiceManager; +import android.os.ServiceManager.ServiceNotFoundException; import java.util.ArrayList; @@ -49,10 +48,8 @@ import java.util.ArrayList; * @see android.content.Context#getSystemService */ public class ClipboardManager extends android.text.ClipboardManager { - private final static Object sStaticLock = new Object(); - private static IClipboard sService; - private final Context mContext; + private final IClipboard mService; private final ArrayList<OnPrimaryClipChangedListener> mPrimaryClipChangedListeners = new ArrayList<OnPrimaryClipChangedListener>(); @@ -93,20 +90,11 @@ public class ClipboardManager extends android.text.ClipboardManager { void onPrimaryClipChanged(); } - static private IClipboard getService() { - synchronized (sStaticLock) { - if (sService != null) { - return sService; - } - IBinder b = ServiceManager.getService("clipboard"); - sService = IClipboard.Stub.asInterface(b); - return sService; - } - } - /** {@hide} */ - public ClipboardManager(Context context, Handler handler) { + public ClipboardManager(Context context, Handler handler) throws ServiceNotFoundException { mContext = context; + mService = IClipboard.Stub.asInterface( + ServiceManager.getServiceOrThrow(Context.CLIPBOARD_SERVICE)); } /** @@ -120,7 +108,7 @@ public class ClipboardManager extends android.text.ClipboardManager { if (clip != null) { clip.prepareToLeaveProcess(true); } - getService().setPrimaryClip(clip, mContext.getOpPackageName()); + mService.setPrimaryClip(clip, mContext.getOpPackageName()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -131,7 +119,7 @@ public class ClipboardManager extends android.text.ClipboardManager { */ public ClipData getPrimaryClip() { try { - return getService().getPrimaryClip(mContext.getOpPackageName()); + return mService.getPrimaryClip(mContext.getOpPackageName()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -143,7 +131,7 @@ public class ClipboardManager extends android.text.ClipboardManager { */ public ClipDescription getPrimaryClipDescription() { try { - return getService().getPrimaryClipDescription(mContext.getOpPackageName()); + return mService.getPrimaryClipDescription(mContext.getOpPackageName()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -154,7 +142,7 @@ public class ClipboardManager extends android.text.ClipboardManager { */ public boolean hasPrimaryClip() { try { - return getService().hasPrimaryClip(mContext.getOpPackageName()); + return mService.hasPrimaryClip(mContext.getOpPackageName()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -164,7 +152,7 @@ public class ClipboardManager extends android.text.ClipboardManager { synchronized (mPrimaryClipChangedListeners) { if (mPrimaryClipChangedListeners.size() == 0) { try { - getService().addPrimaryClipChangedListener( + mService.addPrimaryClipChangedListener( mPrimaryClipChangedServiceListener, mContext.getOpPackageName()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); @@ -179,7 +167,7 @@ public class ClipboardManager extends android.text.ClipboardManager { mPrimaryClipChangedListeners.remove(what); if (mPrimaryClipChangedListeners.size() == 0) { try { - getService().removePrimaryClipChangedListener( + mService.removePrimaryClipChangedListener( mPrimaryClipChangedServiceListener); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); @@ -217,7 +205,7 @@ public class ClipboardManager extends android.text.ClipboardManager { @Deprecated public boolean hasText() { try { - return getService().hasClipboardText(mContext.getOpPackageName()); + return mService.hasClipboardText(mContext.getOpPackageName()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } diff --git a/core/java/android/content/pm/IntentFilterVerificationInfo.java b/core/java/android/content/pm/IntentFilterVerificationInfo.java index 953b051ae6da..f47ad1fb03e9 100644 --- a/core/java/android/content/pm/IntentFilterVerificationInfo.java +++ b/core/java/android/content/pm/IntentFilterVerificationInfo.java @@ -60,9 +60,9 @@ public final class IntentFilterVerificationInfo implements Parcelable { mMainStatus = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED; } - public IntentFilterVerificationInfo(String packageName, ArrayList<String> domains) { + public IntentFilterVerificationInfo(String packageName, ArraySet<String> domains) { mPackageName = packageName; - mDomains.addAll(domains); + mDomains = domains; mMainStatus = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED; } @@ -96,8 +96,8 @@ public final class IntentFilterVerificationInfo implements Parcelable { return mDomains; } - public void setDomains(ArrayList<String> list) { - mDomains = new ArraySet<>(list); + public void setDomains(ArraySet<String> list) { + mDomains = list; } public String getDomainsString() { diff --git a/core/java/android/hardware/ConsumerIrManager.java b/core/java/android/hardware/ConsumerIrManager.java index 9fa1c3f73823..b221e1604949 100644 --- a/core/java/android/hardware/ConsumerIrManager.java +++ b/core/java/android/hardware/ConsumerIrManager.java @@ -19,6 +19,7 @@ package android.hardware; import android.content.Context; import android.os.RemoteException; import android.os.ServiceManager; +import android.os.ServiceManager.ServiceNotFoundException; import android.util.Log; /** @@ -40,10 +41,10 @@ public final class ConsumerIrManager { /** * @hide to prevent subclassing from outside of the framework */ - public ConsumerIrManager(Context context) { + public ConsumerIrManager(Context context) throws ServiceNotFoundException { mPackageName = context.getPackageName(); mService = IConsumerIrService.Stub.asInterface( - ServiceManager.getService(Context.CONSUMER_IR_SERVICE)); + ServiceManager.getServiceOrThrow(Context.CONSUMER_IR_SERVICE)); } /** diff --git a/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java b/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java index c23bd5bcee47..b10c341eb5ec 100644 --- a/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java +++ b/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java @@ -286,23 +286,29 @@ public class CameraCaptureSessionImpl extends CameraCaptureSession } @Override - public synchronized void abortCaptures() throws CameraAccessException { - checkNotClosed(); + public void abortCaptures() throws CameraAccessException { + synchronized (this) { + checkNotClosed(); - if (DEBUG) { - Log.v(TAG, mIdString + "abortCaptures"); - } + if (DEBUG) { + Log.v(TAG, mIdString + "abortCaptures"); + } - if (mAborting) { - Log.w(TAG, mIdString + "abortCaptures - Session is already aborting; doing nothing"); - return; - } + if (mAborting) { + Log.w(TAG, mIdString + "abortCaptures - Session is already aborting; doing nothing"); + return; + } - mAborting = true; - mAbortDrainer.taskStarted(); + mAborting = true; + mAbortDrainer.taskStarted(); + } - mDeviceImpl.flush(); - // The next BUSY -> IDLE set of transitions will mark the end of the abort. + synchronized (mDeviceImpl.mInterfaceLock) { + synchronized (this) { + mDeviceImpl.flush(); + // The next BUSY -> IDLE set of transitions will mark the end of the abort. + } + } } @Override @@ -330,78 +336,86 @@ public class CameraCaptureSessionImpl extends CameraCaptureSession * @see CameraCaptureSession#close */ @Override - public synchronized void replaceSessionClose() { - /* - * In order for creating new sessions to be fast, the new session should be created - * before the old session is closed. - * - * Otherwise the old session will always unconfigure if there is no new session to - * replace it. - * - * Unconfiguring could add hundreds of milliseconds of delay. We could race and attempt - * to skip unconfigure if a new session is created before the captures are all drained, - * but this would introduce nondeterministic behavior. - */ - - if (DEBUG) Log.v(TAG, mIdString + "replaceSessionClose"); - - // Set up fast shutdown. Possible alternative paths: - // - This session is active, so close() below starts the shutdown drain - // - This session is mid-shutdown drain, and hasn't yet reached the idle drain listener. - // - This session is already closed and has executed the idle drain listener, and - // configureOutputsChecked(null) has already been called. - // - // Do not call configureOutputsChecked(null) going forward, since it would race with the - // configuration for the new session. If it was already called, then we don't care, since it - // won't get called again. - mSkipUnconfigure = true; + public void replaceSessionClose() { + synchronized (this) { + /* + * In order for creating new sessions to be fast, the new session should be created + * before the old session is closed. + * + * Otherwise the old session will always unconfigure if there is no new session to + * replace it. + * + * Unconfiguring could add hundreds of milliseconds of delay. We could race and attempt + * to skip unconfigure if a new session is created before the captures are all drained, + * but this would introduce nondeterministic behavior. + */ + if (DEBUG) Log.v(TAG, mIdString + "replaceSessionClose"); + + // Set up fast shutdown. Possible alternative paths: + // - This session is active, so close() below starts the shutdown drain + // - This session is mid-shutdown drain, and hasn't yet reached the idle drain listener. + // - This session is already closed and has executed the idle drain listener, and + // configureOutputsChecked(null) has already been called. + // + // Do not call configureOutputsChecked(null) going forward, since it would race with the + // configuration for the new session. If it was already called, then we don't care, + // since it won't get called again. + mSkipUnconfigure = true; + } close(); } @Override - public synchronized void close() { - - if (mClosed) { - if (DEBUG) Log.v(TAG, mIdString + "close - reentering"); - return; - } + public void close() { + synchronized (this) { + if (mClosed) { + if (DEBUG) Log.v(TAG, mIdString + "close - reentering"); + return; + } - if (DEBUG) Log.v(TAG, mIdString + "close - first time"); + if (DEBUG) Log.v(TAG, mIdString + "close - first time"); - mClosed = true; + mClosed = true; + } - /* - * Flush out any repeating request. Since camera is closed, no new requests - * can be queued, and eventually the entire request queue will be drained. - * - * If the camera device was already closed, short circuit and do nothing; since - * no more internal device callbacks will fire anyway. - * - * Otherwise, once stopRepeating is done, wait for camera to idle, then unconfigure the - * camera. Once that's done, fire #onClosed. - */ - try { - mDeviceImpl.stopRepeating(); - } catch (IllegalStateException e) { - // OK: Camera device may already be closed, nothing else to do + synchronized (mDeviceImpl.mInterfaceLock) { + synchronized (this) { + /* + * Flush out any repeating request. Since camera is closed, no new requests + * can be queued, and eventually the entire request queue will be drained. + * + * If the camera device was already closed, short circuit and do nothing; since + * no more internal device callbacks will fire anyway. + * + * Otherwise, once stopRepeating is done, wait for camera to idle, then unconfigure + * the camera. Once that's done, fire #onClosed. + */ + try { + mDeviceImpl.stopRepeating(); + } catch (IllegalStateException e) { + // OK: Camera device may already be closed, nothing else to do - // TODO: Fire onClosed anytime we get the device onClosed or the ISE? - // or just suppress the ISE only and rely onClosed. - // Also skip any of the draining work if this is already closed. + // TODO: Fire onClosed anytime we get the device onClosed or the ISE? + // or just suppress the ISE only and rely onClosed. + // Also skip any of the draining work if this is already closed. - // Short-circuit; queue callback immediately and return - mStateCallback.onClosed(this); - return; - } catch (CameraAccessException e) { - // OK: close does not throw checked exceptions. - Log.e(TAG, mIdString + "Exception while stopping repeating: ", e); + // Short-circuit; queue callback immediately and return + mStateCallback.onClosed(this); + return; + } catch (CameraAccessException e) { + // OK: close does not throw checked exceptions. + Log.e(TAG, mIdString + "Exception while stopping repeating: ", e); - // TODO: call onError instead of onClosed if this happens + // TODO: call onError instead of onClosed if this happens + } + } } - // If no sequences are pending, fire #onClosed immediately - mSequenceDrainer.beginDrain(); + synchronized (this) { + // If no sequences are pending, fire #onClosed immediately + mSequenceDrainer.beginDrain(); + } } /** diff --git a/core/java/android/hardware/input/InputManager.java b/core/java/android/hardware/input/InputManager.java index 803337b016f9..2b0593fd3817 100644 --- a/core/java/android/hardware/input/InputManager.java +++ b/core/java/android/hardware/input/InputManager.java @@ -33,6 +33,7 @@ import android.os.RemoteException; import android.os.ServiceManager; import android.os.SystemClock; import android.os.Vibrator; +import android.os.ServiceManager.ServiceNotFoundException; import android.provider.Settings; import android.provider.Settings.SettingNotFoundException; import android.util.Log; @@ -225,8 +226,12 @@ public final class InputManager { public static InputManager getInstance() { synchronized (InputManager.class) { if (sInstance == null) { - IBinder b = ServiceManager.getService(Context.INPUT_SERVICE); - sInstance = new InputManager(IInputManager.Stub.asInterface(b)); + try { + sInstance = new InputManager(IInputManager.Stub + .asInterface(ServiceManager.getServiceOrThrow(Context.INPUT_SERVICE))); + } catch (ServiceNotFoundException e) { + throw new IllegalStateException(e); + } } return sInstance; } diff --git a/core/java/android/hardware/location/ContextHubManager.java b/core/java/android/hardware/location/ContextHubManager.java index 3bc15621be3a..2aed53c7deb4 100644 --- a/core/java/android/hardware/location/ContextHubManager.java +++ b/core/java/android/hardware/location/ContextHubManager.java @@ -18,10 +18,10 @@ package android.hardware.location; import android.annotation.SystemApi; import android.content.Context; import android.os.Handler; -import android.os.IBinder; import android.os.Looper; import android.os.RemoteException; import android.os.ServiceManager; +import android.os.ServiceManager.ServiceNotFoundException; import android.util.Log; /** @@ -38,7 +38,7 @@ public final class ContextHubManager { private static final String TAG = "ContextHubManager"; private final Looper mMainLooper; - private IContextHubService mContextHubService; + private final IContextHubService mService; private Callback mCallback; private Handler mCallbackHandler; @@ -92,13 +92,11 @@ public final class ContextHubManager { * @return array of context hub handles */ public int[] getContextHubHandles() { - int[] retVal = null; try { - retVal = getBinder().getContextHubHandles(); + return mService.getContextHubHandles(); } catch (RemoteException e) { - Log.w(TAG, "Could not fetch context hub handles : " + e); + throw e.rethrowFromSystemServer(); } - return retVal; } /** @@ -110,14 +108,11 @@ public final class ContextHubManager { * @see ContextHubInfo */ public ContextHubInfo getContextHubInfo(int hubHandle) { - ContextHubInfo retVal = null; try { - retVal = getBinder().getContextHubInfo(hubHandle); + return mService.getContextHubInfo(hubHandle); } catch (RemoteException e) { - Log.w(TAG, "Could not fetch context hub info :" + e); + throw e.rethrowFromSystemServer(); } - - return retVal; } /** @@ -132,19 +127,11 @@ public final class ContextHubManager { * @see NanoApp */ public int loadNanoApp(int hubHandle, NanoApp app) { - int retVal = -1; - - if (app == null) { - return retVal; - } - try { - retVal = getBinder().loadNanoApp(hubHandle, app); + return mService.loadNanoApp(hubHandle, app); } catch (RemoteException e) { - Log.w(TAG, "Could not load nanoApp :" + e); + throw e.rethrowFromSystemServer(); } - - return retVal; } /** @@ -155,15 +142,11 @@ public final class ContextHubManager { * @return int 0 on success, -1 otherwise */ public int unloadNanoApp(int nanoAppHandle) { - int retVal = -1; - try { - retVal = getBinder().unloadNanoApp(nanoAppHandle); + return mService.unloadNanoApp(nanoAppHandle); } catch (RemoteException e) { - Log.w(TAG, "Could not fetch unload nanoApp :" + e); + throw e.rethrowFromSystemServer(); } - - return retVal; } /** @@ -175,15 +158,11 @@ public final class ContextHubManager { * @see NanoAppInstanceInfo */ public NanoAppInstanceInfo getNanoAppInstanceInfo(int nanoAppHandle) { - NanoAppInstanceInfo retVal = null; - try { - retVal = getBinder().getNanoAppInstanceInfo(nanoAppHandle); + return mService.getNanoAppInstanceInfo(nanoAppHandle); } catch (RemoteException e) { - Log.w(TAG, "Could not fetch nanoApp info :" + e); + throw e.rethrowFromSystemServer(); } - - return retVal; } /** @@ -197,13 +176,11 @@ public final class ContextHubManager { * @return int[] Array of handles to any found nano apps */ public int[] findNanoAppOnHub(int hubHandle, NanoAppFilter filter) { - int[] retVal = null; try { - retVal = getBinder().findNanoAppOnHub(hubHandle, filter); + return mService.findNanoAppOnHub(hubHandle, filter); } catch (RemoteException e) { - Log.w(TAG, "Could not query nanoApp instance :" + e); + throw e.rethrowFromSystemServer(); } - return retVal; } /** @@ -218,19 +195,11 @@ public final class ContextHubManager { * @return int 0 on success, -1 otherwise */ public int sendMessage(int hubHandle, int nanoAppHandle, ContextHubMessage message) { - int retVal = -1; - - if (message == null || message.getData() == null) { - Log.w(TAG, "null ptr"); - return retVal; - } try { - retVal = getBinder().sendMessage(hubHandle, nanoAppHandle, message); + return mService.sendMessage(hubHandle, nanoAppHandle, message); } catch (RemoteException e) { - Log.w(TAG, "Could not send message :" + e.toString()); + throw e.rethrowFromSystemServer(); } - - return retVal; } /** @@ -318,7 +287,7 @@ public final class ContextHubManager { return 0; } - private IContextHubCallback.Stub mClientCallback = new IContextHubCallback.Stub() { + private final IContextHubCallback.Stub mClientCallback = new IContextHubCallback.Stub() { @Override public void onMessageReceipt(final int hubId, final int nanoAppId, final ContextHubMessage message) { @@ -346,29 +315,17 @@ public final class ContextHubManager { } }; - /** @hide */ - public ContextHubManager(Context context, Looper mainLooper) { + /** @throws ServiceNotFoundException + * @hide */ + public ContextHubManager(Context context, Looper mainLooper) throws ServiceNotFoundException { mMainLooper = mainLooper; + mService = IContextHubService.Stub.asInterface( + ServiceManager.getServiceOrThrow(ContextHubService.CONTEXTHUB_SERVICE)); - IBinder b = ServiceManager.getService(ContextHubService.CONTEXTHUB_SERVICE); - if (b != null) { - mContextHubService = IContextHubService.Stub.asInterface(b); - - try { - getBinder().registerCallback(mClientCallback); - } catch (RemoteException e) { - Log.w(TAG, "Could not register callback:" + e); - } - - } else { - Log.w(TAG, "failed to getService"); - } - } - - private IContextHubService getBinder() throws RemoteException { - if (mContextHubService == null) { - throw new RemoteException("Service not connected."); + try { + mService.registerCallback(mClientCallback); + } catch (RemoteException e) { + Log.w(TAG, "Could not register callback:" + e); } - return mContextHubService; } } diff --git a/core/java/android/hardware/location/ContextHubService.java b/core/java/android/hardware/location/ContextHubService.java index 062c9580c1e4..893ed3f7c201 100644 --- a/core/java/android/hardware/location/ContextHubService.java +++ b/core/java/android/hardware/location/ContextHubService.java @@ -154,6 +154,9 @@ public class ContextHubService extends IContextHubService.Stub { Log.e(TAG, "Invalid contextHubhandle " + contextHubHandle); return -1; } + if (app == null) { + return -1; + } int[] msgHeader = new int[MSG_LOAD_APP_HEADER_SIZE]; msgHeader[HEADER_FIELD_HUB_HANDLE] = contextHubHandle; @@ -240,6 +243,11 @@ public class ContextHubService extends IContextHubService.Stub { throws RemoteException { checkPermissions(); + if (msg == null || msg.getData() == null) { + Log.w(TAG, "null ptr"); + return -1; + } + int[] msgHeader = new int[MSG_HEADER_SIZE]; msgHeader[HEADER_FIELD_HUB_HANDLE] = hubHandle; msgHeader[HEADER_FIELD_APP_INSTANCE] = nanoAppHandle; diff --git a/core/java/android/net/NetworkScoreManager.java b/core/java/android/net/NetworkScoreManager.java index 01c160f1bc45..c2286ad8ae13 100644 --- a/core/java/android/net/NetworkScoreManager.java +++ b/core/java/android/net/NetworkScoreManager.java @@ -23,9 +23,9 @@ import android.annotation.SystemApi; import android.content.Context; import android.content.Intent; import android.net.NetworkScorerAppManager.NetworkScorerAppData; -import android.os.IBinder; import android.os.RemoteException; import android.os.ServiceManager; +import android.os.ServiceManager.ServiceNotFoundException; import android.os.UserHandle; /** @@ -127,10 +127,10 @@ public class NetworkScoreManager { private final INetworkScoreService mService; /** @hide */ - public NetworkScoreManager(Context context) { + public NetworkScoreManager(Context context) throws ServiceNotFoundException { mContext = context; - IBinder iBinder = ServiceManager.getService(Context.NETWORK_SCORE_SERVICE); - mService = INetworkScoreService.Stub.asInterface(iBinder); + mService = INetworkScoreService.Stub + .asInterface(ServiceManager.getServiceOrThrow(Context.NETWORK_SCORE_SERVICE)); } /** diff --git a/core/java/android/os/BatteryManager.java b/core/java/android/os/BatteryManager.java index d39968a09023..252385faf089 100644 --- a/core/java/android/os/BatteryManager.java +++ b/core/java/android/os/BatteryManager.java @@ -16,11 +16,6 @@ package android.os; -import android.content.Context; -import android.os.BatteryProperty; -import android.os.IBatteryPropertiesRegistrar; -import android.os.RemoteException; -import android.os.ServiceManager; import com.android.internal.app.IBatteryStats; /** @@ -218,6 +213,13 @@ public class BatteryManager { ServiceManager.getService("batteryproperties")); } + /** {@hide} */ + public BatteryManager(IBatteryStats batteryStats, + IBatteryPropertiesRegistrar batteryPropertiesRegistrar) { + mBatteryStats = batteryStats; + mBatteryPropertiesRegistrar = batteryPropertiesRegistrar; + } + /** * Return true if the battery is currently considered to be charging. This means that * the device is plugged in and is supplying sufficient power that the battery level is diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java index 68aaa1f14eb4..91fe3524e1ad 100644 --- a/core/java/android/os/Build.java +++ b/core/java/android/os/Build.java @@ -677,9 +677,9 @@ public class Build { * <li> {@link android.app.DownloadManager.Request#setAllowedNetworkTypes * DownloadManager.Request.setAllowedNetworkTypes} * will disable "allow over metered" when specifying only - * {@link android.app.DownloadManager.Request#NETWORK_WIFI}. + * {@link android.app.DownloadManager.Request#NETWORK_WIFI}.</li> * <li> {@link android.app.DownloadManager} no longer allows access to raw - * file paths. + * file paths.</li> * <li> {@link android.app.Notification.Builder#setShowWhen * Notification.Builder.setShowWhen} * must be called explicitly to have the time shown, and various other changes in diff --git a/core/java/android/os/ServiceManager.java b/core/java/android/os/ServiceManager.java index 2ba4aa433713..640105ce8f98 100644 --- a/core/java/android/os/ServiceManager.java +++ b/core/java/android/os/ServiceManager.java @@ -16,10 +16,10 @@ package android.os; -import com.android.internal.os.BinderInternal; - import android.util.Log; +import com.android.internal.os.BinderInternal; + import java.util.HashMap; import java.util.Map; @@ -61,6 +61,21 @@ public final class ServiceManager { } /** + * Returns a reference to a service with the given name, or throws + * {@link NullPointerException} if none is found. + * + * @hide + */ + public static IBinder getServiceOrThrow(String name) throws ServiceNotFoundException { + final IBinder binder = getService(name); + if (binder != null) { + return binder; + } else { + throw new ServiceNotFoundException(name); + } + } + + /** * Place a new @a service called @a name into the service * manager. * @@ -138,4 +153,17 @@ public final class ServiceManager { } sCache.putAll(cache); } + + /** + * Exception thrown when no service published for given name. This might be + * thrown early during boot before certain services have published + * themselves. + * + * @hide + */ + public static class ServiceNotFoundException extends Exception { + public ServiceNotFoundException(String name) { + super("No service published for: " + name); + } + } } diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java index cfd016ede062..06e293176177 100644 --- a/core/java/android/os/UserManager.java +++ b/core/java/android/os/UserManager.java @@ -615,7 +615,8 @@ public class UserManager { /** * Specifies if a user is not allowed to enable the oem unlock setting. The default value is - * <code>false</code>. + * <code>false</code>. Setting this restriction has no effect if the bootloader is already + * unlocked. * * @see DevicePolicyManager#addUserRestriction(ComponentName, String) * @see DevicePolicyManager#clearUserRestriction(ComponentName, String) diff --git a/core/java/android/os/health/SystemHealthManager.java b/core/java/android/os/health/SystemHealthManager.java index 32e8425cbe07..7c0af2508a93 100644 --- a/core/java/android/os/health/SystemHealthManager.java +++ b/core/java/android/os/health/SystemHealthManager.java @@ -21,6 +21,7 @@ import android.os.BatteryStats; import android.os.Process; import android.os.RemoteException; import android.os.ServiceManager; +import android.os.ServiceManager.ServiceNotFoundException; import com.android.internal.app.IBatteryStats; @@ -47,8 +48,12 @@ public class SystemHealthManager { * @hide */ public SystemHealthManager() { - mBatteryStats = IBatteryStats.Stub.asInterface( - ServiceManager.getService(BatteryStats.SERVICE_NAME)); + this(IBatteryStats.Stub.asInterface(ServiceManager.getService(BatteryStats.SERVICE_NAME))); + } + + /** {@hide} */ + public SystemHealthManager(IBatteryStats batteryStats) { + mBatteryStats = batteryStats; } /** diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java index c5507b9841bc..cee7553750f6 100644 --- a/core/java/android/os/storage/StorageManager.java +++ b/core/java/android/os/storage/StorageManager.java @@ -35,6 +35,7 @@ import android.os.Message; import android.os.ParcelFileDescriptor; import android.os.RemoteException; import android.os.ServiceManager; +import android.os.ServiceManager.ServiceNotFoundException; import android.os.SystemProperties; import android.os.UserHandle; import android.provider.Settings; @@ -341,7 +342,7 @@ public class StorageManager { * Constructs a StorageManager object through which an application can * can communicate with the systems mount service. * - * @param tgtLooper The {@link android.os.Looper} which events will be received on. + * @param looper The {@link android.os.Looper} which events will be received on. * * <p>Applications can get instance of this class by calling * {@link android.content.Context#getSystemService(java.lang.String)} with an argument @@ -349,14 +350,11 @@ public class StorageManager { * * @hide */ - public StorageManager(Context context, Looper looper) { + public StorageManager(Context context, Looper looper) throws ServiceNotFoundException { mContext = context; mResolver = context.getContentResolver(); mLooper = looper; - mMountService = IMountService.Stub.asInterface(ServiceManager.getService("mount")); - if (mMountService == null) { - throw new IllegalStateException("Failed to find running mount service"); - } + mMountService = IMountService.Stub.asInterface(ServiceManager.getServiceOrThrow("mount")); } /** diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 0b082def0c8a..bff4d7dad888 100755 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -6026,6 +6026,17 @@ public final class Settings { public static final String ASSIST_SCREENSHOT_ENABLED = "assist_screenshot_enabled"; /** + * Specifies whether the screen will show an animation if screen contents are sent to the + * assist application (active voice interaction service). + * + * Note that the disclosure will be forced for third-party assistants or if the device + * does not support disabling it. + * + * @hide + */ + public static final String ASSIST_DISCLOSURE_ENABLED = "assist_disclosure_enabled"; + + /** * Names of the service components that the current user has explicitly allowed to * see all of the user's notifications, separated by ':'. * diff --git a/core/java/android/service/persistentdata/PersistentDataBlockManager.java b/core/java/android/service/persistentdata/PersistentDataBlockManager.java index cfeed51da86f..0f92ed04a457 100644 --- a/core/java/android/service/persistentdata/PersistentDataBlockManager.java +++ b/core/java/android/service/persistentdata/PersistentDataBlockManager.java @@ -163,10 +163,9 @@ public class PersistentDataBlockManager { /** * Retrieves available information about this device's flash lock state. * - * @return FLASH_LOCK_STATE_LOCKED if device bootloader is locked, - * FLASH_LOCK_STATE_UNLOCKED if device bootloader is unlocked, - * or FLASH_LOCK_STATE unknown if this information cannot be ascertained - * on this device. + * @return {@link #FLASH_LOCK_LOCKED} if device bootloader is locked, + * {@link #FLASH_LOCK_UNLOCKED} if device bootloader is unlocked, or {@link #FLASH_LOCK_UNKNOWN} + * if this information cannot be ascertained on this device. */ @FlashLockState public int getFlashLockState() { diff --git a/core/java/android/text/method/LinkMovementMethod.java b/core/java/android/text/method/LinkMovementMethod.java index 3855ff3ae44b..24c119f29d71 100644 --- a/core/java/android/text/method/LinkMovementMethod.java +++ b/core/java/android/text/method/LinkMovementMethod.java @@ -29,6 +29,9 @@ import android.widget.TextView; /** * A movement method that traverses links in the text buffer and scrolls if necessary. * Supports clicking on links with DPad Center or Enter. + * + * <p>Note: Starting from Android 8.0 (API level 25) this class no longer handles the touch + * clicks. */ public class LinkMovementMethod extends ScrollingMovementMethod { private static final int CLICK = 1; @@ -98,14 +101,14 @@ public class LinkMovementMethod extends ScrollingMovementMethod { int padding = widget.getTotalPaddingTop() + widget.getTotalPaddingBottom(); - int areatop = widget.getScrollY(); - int areabot = areatop + widget.getHeight() - padding; + int areaTop = widget.getScrollY(); + int areaBot = areaTop + widget.getHeight() - padding; - int linetop = layout.getLineForVertical(areatop); - int linebot = layout.getLineForVertical(areabot); + int lineTop = layout.getLineForVertical(areaTop); + int lineBot = layout.getLineForVertical(areaBot); - int first = layout.getLineStart(linetop); - int last = layout.getLineEnd(linebot); + int first = layout.getLineStart(lineTop); + int last = layout.getLineEnd(lineBot); ClickableSpan[] candidates = buffer.getSpans(first, last, ClickableSpan.class); @@ -141,46 +144,46 @@ public class LinkMovementMethod extends ScrollingMovementMethod { break; case UP: - int beststart, bestend; + int bestStart, bestEnd; - beststart = -1; - bestend = -1; + bestStart = -1; + bestEnd = -1; for (int i = 0; i < candidates.length; i++) { int end = buffer.getSpanEnd(candidates[i]); if (end < selEnd || selStart == selEnd) { - if (end > bestend) { - beststart = buffer.getSpanStart(candidates[i]); - bestend = end; + if (end > bestEnd) { + bestStart = buffer.getSpanStart(candidates[i]); + bestEnd = end; } } } - if (beststart >= 0) { - Selection.setSelection(buffer, bestend, beststart); + if (bestStart >= 0) { + Selection.setSelection(buffer, bestEnd, bestStart); return true; } break; case DOWN: - beststart = Integer.MAX_VALUE; - bestend = Integer.MAX_VALUE; + bestStart = Integer.MAX_VALUE; + bestEnd = Integer.MAX_VALUE; for (int i = 0; i < candidates.length; i++) { int start = buffer.getSpanStart(candidates[i]); if (start > selStart || selStart == selEnd) { - if (start < beststart) { - beststart = start; - bestend = buffer.getSpanEnd(candidates[i]); + if (start < bestStart) { + bestStart = start; + bestEnd = buffer.getSpanEnd(candidates[i]); } } } - if (bestend < Integer.MAX_VALUE) { - Selection.setSelection(buffer, beststart, bestend); + if (bestEnd < Integer.MAX_VALUE) { + Selection.setSelection(buffer, bestStart, bestEnd); return true; } @@ -195,8 +198,7 @@ public class LinkMovementMethod extends ScrollingMovementMethod { MotionEvent event) { int action = event.getAction(); - if (action == MotionEvent.ACTION_UP || - action == MotionEvent.ACTION_DOWN) { + if (action == MotionEvent.ACTION_DOWN) { int x = (int) event.getX(); int y = (int) event.getY(); @@ -210,17 +212,12 @@ public class LinkMovementMethod extends ScrollingMovementMethod { int line = layout.getLineForVertical(y); int off = layout.getOffsetForHorizontal(line, x); - ClickableSpan[] link = buffer.getSpans(off, off, ClickableSpan.class); - - if (link.length != 0) { - if (action == MotionEvent.ACTION_UP) { - link[0].onClick(widget); - } else if (action == MotionEvent.ACTION_DOWN) { - Selection.setSelection(buffer, - buffer.getSpanStart(link[0]), - buffer.getSpanEnd(link[0])); - } + ClickableSpan[] links = buffer.getSpans(off, off, ClickableSpan.class); + if (links.length != 0) { + Selection.setSelection(buffer, + buffer.getSpanStart(links[0]), + buffer.getSpanEnd(links[0])); return true; } else { Selection.removeSelection(buffer); diff --git a/core/java/android/util/TimedRemoteCaller.java b/core/java/android/util/TimedRemoteCaller.java index abb2b6401d71..100c16e7f990 100644 --- a/core/java/android/util/TimedRemoteCaller.java +++ b/core/java/android/util/TimedRemoteCaller.java @@ -17,6 +17,7 @@ package android.util; import android.os.SystemClock; +import com.android.internal.annotations.GuardedBy; import java.util.concurrent.TimeoutException; @@ -29,8 +30,7 @@ import java.util.concurrent.TimeoutException; * the sequence number. If the response comes within the timeout * and its sequence number is the one sent in the method invocation, * then the call succeeded. If the response does not come within - * the timeout then the call failed. Older result received when - * waiting for the result are ignored. + * the timeout then the call failed. * <p> * Typical usage is: * </p> @@ -66,66 +66,90 @@ public abstract class TimedRemoteCaller<T> { public static final long DEFAULT_CALL_TIMEOUT_MILLIS = 5000; - private static final int UNDEFINED_SEQUENCE = -1; - private final Object mLock = new Object(); private final long mCallTimeoutMillis; - private int mSequenceCounter; - - private int mReceivedSequence = UNDEFINED_SEQUENCE; + /** The callbacks we are waiting for, key == sequence id, value == 1 */ + @GuardedBy("mLock") + private final SparseIntArray mAwaitedCalls = new SparseIntArray(1); - private int mAwaitedSequence = UNDEFINED_SEQUENCE; + /** The callbacks we received but for which the result has not yet been reported */ + @GuardedBy("mLock") + private final SparseArray<T> mReceivedCalls = new SparseArray<>(1); - private T mResult; + @GuardedBy("mLock") + private int mSequenceCounter; + /** + * Create a new timed caller. + * + * @param callTimeoutMillis The time to wait in {@link #getResultTimed} before a timed call will + * be declared timed out + */ public TimedRemoteCaller(long callTimeoutMillis) { mCallTimeoutMillis = callTimeoutMillis; } - public final int onBeforeRemoteCall() { + /** + * Indicate that a timed call will be made. + * + * @return The sequence id for the call + */ + protected final int onBeforeRemoteCall() { synchronized (mLock) { - mAwaitedSequence = mSequenceCounter++; - return mAwaitedSequence; - } - } + int sequenceId; + do { + sequenceId = mSequenceCounter++; + } while (mAwaitedCalls.get(sequenceId) != 0); - public final T getResultTimed(int sequence) throws TimeoutException { - synchronized (mLock) { - final boolean success = waitForResultTimedLocked(sequence); - if (!success) { - throw new TimeoutException("No reponse for sequence: " + sequence); - } - T result = mResult; - mResult = null; - return result; + mAwaitedCalls.put(sequenceId, 1); + + return sequenceId; } } - public final void onRemoteMethodResult(T result, int sequence) { + /** + * Indicate that the timed call has returned. + * + * @param result The result of the timed call + * @param sequence The sequence id of the call (from {@link #onBeforeRemoteCall()}) + */ + protected final void onRemoteMethodResult(T result, int sequence) { synchronized (mLock) { - if (sequence == mAwaitedSequence) { - mReceivedSequence = sequence; - mResult = result; + // Do nothing if we do not await the call anymore as it must have timed out + boolean containedSequenceId = mAwaitedCalls.get(sequence) != 0; + if (containedSequenceId) { + mAwaitedCalls.delete(sequence); + mReceivedCalls.put(sequence, result); mLock.notifyAll(); } } } - private boolean waitForResultTimedLocked(int sequence) { + /** + * Wait until the timed call has returned. + * + * @param sequence The sequence id of the call (from {@link #onBeforeRemoteCall()}) + * + * @return The result of the timed call (set in {@link #onRemoteMethodResult(Object, int)}) + */ + protected final T getResultTimed(int sequence) throws TimeoutException { final long startMillis = SystemClock.uptimeMillis(); while (true) { try { - if (mReceivedSequence == sequence) { - return true; - } - final long elapsedMillis = SystemClock.uptimeMillis() - startMillis; - final long waitMillis = mCallTimeoutMillis - elapsedMillis; - if (waitMillis <= 0) { - return false; + synchronized (mLock) { + if (mReceivedCalls.indexOfKey(sequence) >= 0) { + return mReceivedCalls.removeReturnOld(sequence); + } + final long elapsedMillis = SystemClock.uptimeMillis() - startMillis; + final long waitMillis = mCallTimeoutMillis - elapsedMillis; + if (waitMillis <= 0) { + mAwaitedCalls.delete(sequence); + throw new TimeoutException("No response for sequence: " + sequence); + } + mLock.wait(waitMillis); } - mLock.wait(waitMillis); } catch (InterruptedException ie) { /* ignore */ } diff --git a/core/java/android/view/SoundEffectConstants.java b/core/java/android/view/SoundEffectConstants.java index 4a77af47170d..8d891bbc2cfc 100644 --- a/core/java/android/view/SoundEffectConstants.java +++ b/core/java/android/view/SoundEffectConstants.java @@ -37,6 +37,8 @@ public class SoundEffectConstants { * or {@link View#FOCUS_BACKWARD} * @return The appropriate sonification constant. + * @throws {@link IllegalArgumentException} when the passed direction is not one of the + * documented values. */ public static int getContantForFocusDirection(int direction) { switch (direction) { diff --git a/core/java/android/view/TextureView.java b/core/java/android/view/TextureView.java index 745da51a1dc1..bb771000b343 100644 --- a/core/java/android/view/TextureView.java +++ b/core/java/android/view/TextureView.java @@ -229,7 +229,6 @@ public class TextureView extends View { @Override protected void destroyHardwareResources() { destroyHardwareLayer(); - mUpdateSurface = mSurface != null; } private void destroyHardwareLayer() { @@ -376,17 +375,17 @@ public class TextureView extends View { } mLayer = mAttachInfo.mThreadedRenderer.createTextureLayer(); - if (!mUpdateSurface) { + boolean createNewSurface = (mSurface == null); + if (createNewSurface) { // Create a new SurfaceTexture for the layer. mSurface = new SurfaceTexture(false); mLayer.setSurfaceTexture(mSurface); nCreateNativeWindow(mSurface); } mSurface.setDefaultBufferSize(getWidth(), getHeight()); - mSurface.setOnFrameAvailableListener(mUpdateListener, mAttachInfo.mHandler); - if (mListener != null && !mUpdateSurface) { + if (mListener != null && createNewSurface) { mListener.onSurfaceTextureAvailable(mSurface, getWidth(), getHeight()); } mLayer.setLayerPaint(mLayerPaint); @@ -745,9 +744,11 @@ public class TextureView extends View { "released SurfaceTexture"); } if (mSurface != null) { + nDestroyNativeWindow(); mSurface.release(); } mSurface = surfaceTexture; + nCreateNativeWindow(mSurface); /* * If the view is visible and we already made a layer, update the diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java index 8ce9ddbfddd2..1034275c8702 100644 --- a/core/java/android/view/ThreadedRenderer.java +++ b/core/java/android/view/ThreadedRenderer.java @@ -520,16 +520,6 @@ public final class ThreadedRenderer { } /** - * This method should be invoked whenever the current threaded renderer - * context should be reset. - * - * @param surface The surface to render - */ - void invalidate(Surface surface) { - updateSurface(surface); - } - - /** * Detaches the layer's surface texture from the GL context and releases * the texture id */ diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index c37cf569a893..5a7f0ff08782 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -20656,7 +20656,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * <li>{@link #DRAG_FLAG_GLOBAL}</li> * <li>{@link #DRAG_FLAG_GLOBAL_PERSISTABLE_URI_PERMISSION}</li> * <li>{@link #DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION}</li> - * <li>{@link #DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION}</li> * <li>{@link #DRAG_FLAG_GLOBAL_URI_READ}</li> * <li>{@link #DRAG_FLAG_GLOBAL_URI_WRITE}</li> * <li>{@link #DRAG_FLAG_OPAQUE}</li> @@ -20674,6 +20673,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Log.w(VIEW_LOG_TAG, "startDragAndDrop called on a detached view."); return false; } + + data.prepareToLeaveProcess((flags & View.DRAG_FLAG_GLOBAL) != 0); + boolean okay = false; Point shadowSize = new Point(); @@ -23864,7 +23866,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * on the screen. */ private boolean shouldDrawRoundScrollbar() { - if (!mResources.getConfiguration().isScreenRound()) { + if (!mResources.getConfiguration().isScreenRound() || mAttachInfo == null) { return false; } diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 2bc1d74ffb79..757727b6f1f8 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -5539,6 +5539,10 @@ public final class ViewRootImpl implements ViewParent, // Remember who the current drag target is pre-dispatch final View prevDragView = mCurrentDragView; + if (what == DragEvent.ACTION_DROP) { + event.getClipData().prepareToEnterProcess(); + } + // Now dispatch the drag/drop event boolean result = mView.dispatchDragEvent(event); diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java index f1fa21694976..0b9f9d09b483 100644 --- a/core/java/android/view/WindowManagerPolicy.java +++ b/core/java/android/view/WindowManagerPolicy.java @@ -484,6 +484,7 @@ public interface WindowManagerPolicy { public void switchInputMethod(boolean forwardDirection); public void shutdown(boolean confirm); + public void reboot(boolean confirm); public void rebootSafeMode(boolean confirm); /** diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java index c0c8e64aacc8..e37cf9621cf1 100644 --- a/core/java/android/view/inputmethod/InputMethodManager.java +++ b/core/java/android/view/inputmethod/InputMethodManager.java @@ -41,6 +41,7 @@ import android.os.RemoteException; import android.os.ResultReceiver; import android.os.ServiceManager; import android.os.Trace; +import android.os.ServiceManager.ServiceNotFoundException; import android.text.TextUtils; import android.text.style.SuggestionSpan; import android.util.Log; @@ -55,6 +56,7 @@ import android.view.InputEventSender; import android.view.KeyEvent; import android.view.View; import android.view.ViewRootImpl; +import android.view.textservice.TextServicesManager; import java.io.FileDescriptor; import java.io.PrintWriter; @@ -622,6 +624,11 @@ public final class InputMethodManager { final InputConnection mDummyInputConnection = new BaseInputConnection(this, false); + InputMethodManager(Looper looper) throws ServiceNotFoundException { + this(IInputMethodManager.Stub.asInterface( + ServiceManager.getServiceOrThrow(Context.INPUT_METHOD_SERVICE)), looper); + } + InputMethodManager(IInputMethodManager service, Looper looper) { mService = service; mMainLooper = looper; @@ -638,9 +645,11 @@ public final class InputMethodManager { public static InputMethodManager getInstance() { synchronized (InputMethodManager.class) { if (sInstance == null) { - IBinder b = ServiceManager.getService(Context.INPUT_METHOD_SERVICE); - IInputMethodManager service = IInputMethodManager.Stub.asInterface(b); - sInstance = new InputMethodManager(service, Looper.getMainLooper()); + try { + sInstance = new InputMethodManager(Looper.getMainLooper()); + } catch (ServiceNotFoundException e) { + throw new IllegalStateException(e); + } } return sInstance; } diff --git a/core/java/android/view/textservice/TextServicesManager.java b/core/java/android/view/textservice/TextServicesManager.java index 89d879ee6ee2..0f168f392a20 100644 --- a/core/java/android/view/textservice/TextServicesManager.java +++ b/core/java/android/view/textservice/TextServicesManager.java @@ -16,16 +16,16 @@ package android.view.textservice; -import com.android.internal.textservice.ITextServicesManager; - import android.content.Context; import android.os.Bundle; -import android.os.IBinder; import android.os.RemoteException; import android.os.ServiceManager; +import android.os.ServiceManager.ServiceNotFoundException; import android.util.Log; import android.view.textservice.SpellCheckerSession.SpellCheckerSessionListener; +import com.android.internal.textservice.ITextServicesManager; + import java.util.Locale; /** @@ -66,13 +66,12 @@ public final class TextServicesManager { private static final boolean DBG = false; private static TextServicesManager sInstance; - private static ITextServicesManager sService; - private TextServicesManager() { - if (sService == null) { - IBinder b = ServiceManager.getService(Context.TEXT_SERVICES_MANAGER_SERVICE); - sService = ITextServicesManager.Stub.asInterface(b); - } + private final ITextServicesManager mService; + + private TextServicesManager() throws ServiceNotFoundException { + mService = ITextServicesManager.Stub.asInterface( + ServiceManager.getServiceOrThrow(Context.TEXT_SERVICES_MANAGER_SERVICE)); } /** @@ -81,12 +80,15 @@ public final class TextServicesManager { */ public static TextServicesManager getInstance() { synchronized (TextServicesManager.class) { - if (sInstance != null) { - return sInstance; + if (sInstance == null) { + try { + sInstance = new TextServicesManager(); + } catch (ServiceNotFoundException e) { + throw new IllegalStateException(e); + } } - sInstance = new TextServicesManager(); + return sInstance; } - return sInstance; } /** @@ -131,7 +133,7 @@ public final class TextServicesManager { final SpellCheckerInfo sci; try { - sci = sService.getCurrentSpellChecker(null); + sci = mService.getCurrentSpellChecker(null); } catch (RemoteException e) { return null; } @@ -170,13 +172,13 @@ public final class TextServicesManager { return null; } final SpellCheckerSession session = new SpellCheckerSession( - sci, sService, listener, subtypeInUse); + sci, mService, listener, subtypeInUse); try { - sService.getSpellCheckerService(sci.getId(), subtypeInUse.getLocale(), + mService.getSpellCheckerService(sci.getId(), subtypeInUse.getLocale(), session.getTextServicesSessionListener(), session.getSpellCheckerSessionListener(), bundle); } catch (RemoteException e) { - return null; + throw e.rethrowFromSystemServer(); } return session; } @@ -186,14 +188,13 @@ public final class TextServicesManager { */ public SpellCheckerInfo[] getEnabledSpellCheckers() { try { - final SpellCheckerInfo[] retval = sService.getEnabledSpellCheckers(); + final SpellCheckerInfo[] retval = mService.getEnabledSpellCheckers(); if (DBG) { Log.d(TAG, "getEnabledSpellCheckers: " + (retval != null ? retval.length : "null")); } return retval; } catch (RemoteException e) { - Log.e(TAG, "Error in getEnabledSpellCheckers: " + e); - return null; + throw e.rethrowFromSystemServer(); } } @@ -203,9 +204,9 @@ public final class TextServicesManager { public SpellCheckerInfo getCurrentSpellChecker() { try { // Passing null as a locale for ICS - return sService.getCurrentSpellChecker(null); + return mService.getCurrentSpellChecker(null); } catch (RemoteException e) { - return null; + throw e.rethrowFromSystemServer(); } } @@ -217,9 +218,9 @@ public final class TextServicesManager { if (sci == null) { throw new NullPointerException("SpellCheckerInfo is null."); } - sService.setCurrentSpellChecker(null, sci.getId()); + mService.setCurrentSpellChecker(null, sci.getId()); } catch (RemoteException e) { - Log.e(TAG, "Error in setCurrentSpellChecker: " + e); + throw e.rethrowFromSystemServer(); } } @@ -229,17 +230,10 @@ public final class TextServicesManager { public SpellCheckerSubtype getCurrentSpellCheckerSubtype( boolean allowImplicitlySelectedSubtype) { try { - if (sService == null) { - // TODO: This is a workaround. Needs to investigate why sService could be null - // here. - Log.e(TAG, "sService is null."); - return null; - } // Passing null as a locale until we support multiple enabled spell checker subtypes. - return sService.getCurrentSpellCheckerSubtype(null, allowImplicitlySelectedSubtype); + return mService.getCurrentSpellCheckerSubtype(null, allowImplicitlySelectedSubtype); } catch (RemoteException e) { - Log.e(TAG, "Error in getCurrentSpellCheckerSubtype: " + e); - return null; + throw e.rethrowFromSystemServer(); } } @@ -254,9 +248,9 @@ public final class TextServicesManager { } else { hashCode = subtype.hashCode(); } - sService.setCurrentSpellCheckerSubtype(null, hashCode); + mService.setCurrentSpellCheckerSubtype(null, hashCode); } catch (RemoteException e) { - Log.e(TAG, "Error in setSpellCheckerSubtype:" + e); + throw e.rethrowFromSystemServer(); } } @@ -265,9 +259,9 @@ public final class TextServicesManager { */ public void setSpellCheckerEnabled(boolean enabled) { try { - sService.setSpellCheckerEnabled(enabled); + mService.setSpellCheckerEnabled(enabled); } catch (RemoteException e) { - Log.e(TAG, "Error in setSpellCheckerEnabled:" + e); + throw e.rethrowFromSystemServer(); } } @@ -276,10 +270,9 @@ public final class TextServicesManager { */ public boolean isSpellCheckerEnabled() { try { - return sService.isSpellCheckerEnabled(); + return mService.isSpellCheckerEnabled(); } catch (RemoteException e) { - Log.e(TAG, "Error in isSpellCheckerEnabled:" + e); - return false; + throw e.rethrowFromSystemServer(); } } } diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java index 66b22ce45f53..5ed6638f2783 100644 --- a/core/java/android/widget/AbsListView.java +++ b/core/java/android/widget/AbsListView.java @@ -1546,7 +1546,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te switch (action) { case AccessibilityNodeInfo.ACTION_SCROLL_FORWARD: case R.id.accessibilityActionScrollDown: { - if (isEnabled() && getLastVisiblePosition() < getCount() - 1) { + if (isEnabled() && canScrollDown()) { final int viewportHeight = getHeight() - mListPadding.top - mListPadding.bottom; smoothScrollBy(viewportHeight, PositionScroller.SCROLL_DURATION); return true; @@ -1554,7 +1554,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te } return false; case AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD: case R.id.accessibilityActionScrollUp: { - if (isEnabled() && mFirstPosition > 0) { + if (isEnabled() && canScrollUp()) { final int viewportHeight = getHeight() - mListPadding.top - mListPadding.bottom; smoothScrollBy(-viewportHeight, PositionScroller.SCROLL_DURATION); return true; diff --git a/core/java/android/widget/RadialTimePickerView.java b/core/java/android/widget/RadialTimePickerView.java index 02ee2df18aaf..6f198e78df8a 100644 --- a/core/java/android/widget/RadialTimePickerView.java +++ b/core/java/android/widget/RadialTimePickerView.java @@ -16,7 +16,11 @@ package android.widget; +import com.android.internal.R; +import com.android.internal.widget.ExploreByTouchHelper; + import android.animation.ObjectAnimator; +import android.annotation.IntDef; import android.content.Context; import android.content.res.ColorStateList; import android.content.res.Resources; @@ -43,9 +47,8 @@ import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction; -import com.android.internal.R; -import com.android.internal.widget.ExploreByTouchHelper; - +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.util.Calendar; import java.util.Locale; @@ -55,11 +58,16 @@ import java.util.Locale; * @hide */ public class RadialTimePickerView extends View { - private static final String TAG = "RadialTimePickerView"; public static final int HOURS = 0; public static final int MINUTES = 1; + + /** @hide */ + @IntDef({HOURS, MINUTES}) + @Retention(RetentionPolicy.SOURCE) + @interface PickerType {} + private static final int HOURS_INNER = 2; private static final int SELECTOR_CIRCLE = 0; @@ -185,8 +193,24 @@ public class RadialTimePickerView extends View { private boolean mInputEnabled = true; - public interface OnValueSelectedListener { - void onValueSelected(int pickerIndex, int newValue, boolean autoAdvance); + interface OnValueSelectedListener { + /** + * Called when the selected value at a given picker index has changed. + * + * @param pickerType the type of value that has changed, one of: + * <ul> + * <li>{@link #MINUTES} + * <li>{@link #HOURS} + * </ul> + * @param newValue the new value as minute in hour (0-59) or hour in + * day (0-23) + * @param autoAdvance when the picker type is {@link #HOURS}, + * {@code true} to switch to the {@link #MINUTES} + * picker or {@code false} to stay on the current + * picker. No effect when picker type is + * {@link #MINUTES}. + */ + void onValueSelected(@PickerType int pickerType, int newValue, boolean autoAdvance); } /** @@ -977,7 +1001,7 @@ public class RadialTimePickerView extends View { // Ensure we're showing the correct picker. animatePicker(mShowHours, ANIM_DURATION_TOUCH); - final int type; + final @PickerType int type; final int newValue; final boolean valueChanged; diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index a6d004fd0ec9..6dafe34fdc13 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -114,6 +114,7 @@ import android.view.ActionMode; import android.view.Choreographer; import android.view.ContextMenu; import android.view.DragEvent; +import android.view.GestureDetector; import android.view.Gravity; import android.view.HapticFeedbackConstants; import android.view.KeyCharacterMap; @@ -650,6 +651,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener */ private Editor mEditor; + private final GestureDetector mClickableSpanOnClickGestureDetector; + private static final int DEVICE_PROVISIONED_UNKNOWN = 0; private static final int DEVICE_PROVISIONED_NO = 1; private static final int DEVICE_PROVISIONED_YES = 2; @@ -1488,6 +1491,24 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener if (getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) { setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES); } + + mClickableSpanOnClickGestureDetector = new GestureDetector(context, + new GestureDetector.SimpleOnGestureListener() { + @Override + public boolean onSingleTapConfirmed(MotionEvent e) { + if (mLinksClickable && (mMovement != null) && + (mMovement instanceof LinkMovementMethod + || (mAutoLinkMask != 0 && isTextSelectable()))) { + ClickableSpan[] links = ((Spannable) mText).getSpans( + getSelectionStart(), getSelectionEnd(), ClickableSpan.class); + if (links.length > 0) { + links[0].onClick(TextView.this); + return true; + } + } + return false; + } + }); } private int[] parseDimensionArray(TypedArray dimens) { @@ -8515,21 +8536,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener if (mMovement != null) { handled |= mMovement.onTouchEvent(this, (Spannable) mText, event); } + handled |= mClickableSpanOnClickGestureDetector.onTouchEvent(event); final boolean textIsSelectable = isTextSelectable(); - if (touchIsFinished && mLinksClickable && mAutoLinkMask != 0 && textIsSelectable) { - // The LinkMovementMethod which should handle taps on links has not been installed - // on non editable text that support text selection. - // We reproduce its behavior here to open links for these. - ClickableSpan[] links = ((Spannable) mText).getSpans(getSelectionStart(), - getSelectionEnd(), ClickableSpan.class); - - if (links.length > 0) { - links[0].onClick(this); - handled = true; - } - } - if (touchIsFinished && (isTextEditable() || textIsSelectable)) { // Show the IME, except when selecting in read-only text. final InputMethodManager imm = InputMethodManager.peekInstance(); diff --git a/core/java/android/widget/TimePickerClockDelegate.java b/core/java/android/widget/TimePickerClockDelegate.java index 59cde5b89b9e..1d37a21c1e7e 100644 --- a/core/java/android/widget/TimePickerClockDelegate.java +++ b/core/java/android/widget/TimePickerClockDelegate.java @@ -62,9 +62,6 @@ class TimePickerClockDelegate extends TimePicker.AbstractTimePickerDelegate { private static final int HOUR_INDEX = RadialTimePickerView.HOURS; private static final int MINUTE_INDEX = RadialTimePickerView.MINUTES; - // NOT a real index for the purpose of what's showing. - private static final int AMPM_INDEX = 2; - private static final int[] ATTRS_TEXT_COLOR = new int[] {R.attr.textColor}; private static final int[] ATTRS_DISABLED_ALPHA = new int[] {R.attr.disabledAlpha}; @@ -725,22 +722,21 @@ class TimePickerClockDelegate extends TimePicker.AbstractTimePickerDelegate { /** Listener for RadialTimePickerView interaction. */ private final OnValueSelectedListener mOnValueSelectedListener = new OnValueSelectedListener() { @Override - public void onValueSelected(int pickerIndex, int newValue, boolean autoAdvance) { - switch (pickerIndex) { - case HOUR_INDEX: + public void onValueSelected(int pickerType, int newValue, boolean autoAdvance) { + switch (pickerType) { + case RadialTimePickerView.HOURS: final boolean isTransition = mAllowAutoAdvance && autoAdvance; setHourInternal(newValue, true, !isTransition); if (isTransition) { setCurrentItemShowing(MINUTE_INDEX, true, false); - mDelegator.announceForAccessibility(newValue + ". " + mSelectMinutes); + + final int localizedHour = getLocalizedHour(newValue); + mDelegator.announceForAccessibility(localizedHour + ". " + mSelectMinutes); } break; - case MINUTE_INDEX: + case RadialTimePickerView.MINUTES: setMinuteInternal(newValue, true); break; - case AMPM_INDEX: - updateAmPmLabelStates(newValue); - break; } if (mOnTimeChangedListener != null) { diff --git a/core/java/com/android/internal/app/AssistUtils.java b/core/java/com/android/internal/app/AssistUtils.java index 56c5cc9b69ec..294007946c77 100644 --- a/core/java/com/android/internal/app/AssistUtils.java +++ b/core/java/com/android/internal/app/AssistUtils.java @@ -16,10 +16,13 @@ package com.android.internal.app; +import com.android.internal.R; + import android.app.SearchManager; import android.content.ComponentName; import android.content.Context; import android.content.Intent; +import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.os.Bundle; @@ -166,4 +169,41 @@ public class AssistUtils { return null; } + public static boolean isPreinstalledAssistant(Context context, ComponentName assistant) { + if (assistant == null) { + return false; + } + ApplicationInfo applicationInfo; + try { + applicationInfo = context.getPackageManager().getApplicationInfo( + assistant.getPackageName(), 0); + } catch (PackageManager.NameNotFoundException e) { + return false; + } + return applicationInfo.isSystemApp() || applicationInfo.isUpdatedSystemApp(); + } + + private static boolean isDisclosureEnabled(Context context) { + return Settings.Secure.getInt(context.getContentResolver(), + Settings.Secure.ASSIST_DISCLOSURE_ENABLED, 0) != 0; + } + + /** + * @return if the disclosure animation should trigger for the given assistant. + * + * Third-party assistants will always need to disclose, while the user can configure this for + * pre-installed assistants. + */ + public static boolean shouldDisclose(Context context, ComponentName assistant) { + if (!allowDisablingAssistDisclosure(context)) { + return true; + } + + return isDisclosureEnabled(context) || !isPreinstalledAssistant(context, assistant); + } + + public static boolean allowDisablingAssistDisclosure(Context context) { + return context.getResources().getBoolean( + com.android.internal.R.bool.config_allowDisablingAssistDisclosure); + } } diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java index fef4a5381485..0aa3a7e9c8a4 100644 --- a/core/java/com/android/internal/os/BatteryStatsImpl.java +++ b/core/java/com/android/internal/os/BatteryStatsImpl.java @@ -111,7 +111,7 @@ public class BatteryStatsImpl extends BatteryStats { private static final int MAGIC = 0xBA757475; // 'BATSTATS' // Current on-disk Parcel version - private static final int VERSION = 149 + (USE_OLD_HISTORY ? 1000 : 0); + private static final int VERSION = 150 + (USE_OLD_HISTORY ? 1000 : 0); // Maximum number of items we will record in the history. private static final int MAX_HISTORY_ITEMS = 2000; @@ -1425,22 +1425,6 @@ public class BatteryStatsImpl extends BatteryStats { mUnpluggedReportedCount = 0; return true; } - - @Override - public void writeSummaryFromParcelLocked(Parcel out, long batteryRealtime) { - super.writeSummaryFromParcelLocked(out, batteryRealtime); - out.writeLong(mCurrentReportedTotalTime); - out.writeInt(mCurrentReportedCount); - out.writeInt(mTrackingReportedValues ? 1 : 0); - } - - @Override - public void readSummaryFromParcelLocked(Parcel in) { - super.readSummaryFromParcelLocked(in); - mUnpluggedReportedTotalTime = mCurrentReportedTotalTime = in.readLong(); - mUnpluggedReportedCount = mCurrentReportedCount = in.readInt(); - mTrackingReportedValues = in.readInt() == 1; - } } /** diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java index 7a4f74fe6d7f..40b9ab682f5f 100644 --- a/core/java/com/android/internal/os/ZygoteInit.java +++ b/core/java/com/android/internal/os/ZygoteInit.java @@ -502,21 +502,42 @@ public class ZygoteInit { // System server is fully AOTed and never profiled // for profile guided compilation. // TODO: Make this configurable between INTERPRET_ONLY, SPEED, SPACE and EVERYTHING? - final int dexoptNeeded = DexFile.getDexOptNeeded( + + int dexoptNeeded; + try { + dexoptNeeded = DexFile.getDexOptNeeded( classPathElement, instructionSet, "speed", false /* newProfile */); + } catch (FileNotFoundException ignored) { + // Do not add to the classpath. + Log.w(TAG, "Missing classpath element for system server: " + classPathElement); + continue; + } catch (IOException e) { + // Not fully clear what to do here as we don't know the cause of the + // IO exception. Add to the classpath to be conservative, but don't + // attempt to compile it. + Log.w(TAG, "Error checking classpath element for system server: " + + classPathElement, e); + dexoptNeeded = DexFile.NO_DEXOPT_NEEDED; + } + if (dexoptNeeded != DexFile.NO_DEXOPT_NEEDED) { - installer.dexopt(classPathElement, Process.SYSTEM_UID, instructionSet, - dexoptNeeded, 0 /*dexFlags*/, "speed", null /*volumeUuid*/, - sharedLibraries); + try { + installer.dexopt(classPathElement, Process.SYSTEM_UID, instructionSet, + dexoptNeeded, 0 /*dexFlags*/, "speed", null /*volumeUuid*/, + sharedLibraries); + } catch (InstallerException e) { + // Ignore (but log), we need this on the classpath for fallback mode. + Log.w(TAG, "Failed compiling classpath element for system server: " + + classPathElement, e); + } } + if (!sharedLibraries.isEmpty()) { sharedLibraries += ":"; } sharedLibraries += classPathElement; } - } catch (IOException | InstallerException e) { - throw new RuntimeException("Error starting system_server", e); } finally { installer.disconnect(); } diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java index 9ad750d3a599..878f3a69a504 100644 --- a/core/java/com/android/internal/policy/PhoneWindow.java +++ b/core/java/com/android/internal/policy/PhoneWindow.java @@ -92,8 +92,6 @@ import android.util.EventLog; import android.util.Log; import android.util.SparseArray; import android.util.TypedValue; -import android.view.accessibility.AccessibilityNodeInfo; -import android.view.accessibility.AccessibilityNodeProvider; import android.view.animation.Animation; import android.view.animation.AnimationUtils; import android.widget.FrameLayout; @@ -2057,9 +2055,6 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { } static private final String FOCUSED_ID_TAG = "android:focusedViewId"; - static private final String ACCESSIBILITY_FOCUSED_ID_TAG = "android:accessibilityFocusedViewId"; - static private final String ACCESSIBILITY_FOCUSED_VIRTUAL_ID_TAG = - "android:accessibilityFocusedVirtualViewId"; static private final String VIEWS_TAG = "android:views"; static private final String PANELS_TAG = "android:Panels"; static private final String ACTION_BAR_TAG = "android:ActionBar"; @@ -2082,26 +2077,6 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { outState.putInt(FOCUSED_ID_TAG, focusedView.getId()); } - // Save the accessibility focused view ID. - if (mDecor != null) { - final ViewRootImpl viewRootImpl = mDecor.getViewRootImpl(); - if (viewRootImpl != null) { - final View accessFocusHost = viewRootImpl.getAccessibilityFocusedHost(); - if (accessFocusHost != null && accessFocusHost.getId() != View.NO_ID) { - outState.putInt(ACCESSIBILITY_FOCUSED_ID_TAG, accessFocusHost.getId()); - - // If we have a focused virtual node ID, save that too. - final AccessibilityNodeInfo accessFocusedNode = - viewRootImpl.getAccessibilityFocusedVirtualView(); - if (accessFocusedNode != null) { - final int virtualNodeId = AccessibilityNodeInfo.getVirtualDescendantId( - accessFocusedNode.getSourceNodeId()); - outState.putInt(ACCESSIBILITY_FOCUSED_VIRTUAL_ID_TAG, virtualNodeId); - } - } - } - } - // save the panels SparseArray<Parcelable> panelStates = new SparseArray<Parcelable>(); savePanelState(panelStates); @@ -2144,13 +2119,6 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { } } - // Restore the accessibility focused view. - final int accessFocusHostViewId = savedInstanceState.getInt( - ACCESSIBILITY_FOCUSED_ID_TAG, View.NO_ID); - final int accessFocusVirtualViewId = savedInstanceState.getInt( - ACCESSIBILITY_FOCUSED_VIRTUAL_ID_TAG, AccessibilityNodeInfo.UNDEFINED_ITEM_ID); - tryRestoreAccessibilityFocus(accessFocusHostViewId, accessFocusVirtualViewId); - // Restore the panels. SparseArray<Parcelable> panelStates = savedInstanceState.getSparseParcelableArray(PANELS_TAG); if (panelStates != null) { @@ -2170,33 +2138,6 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { } } - private void tryRestoreAccessibilityFocus(int hostViewId, int virtualViewId) { - if (hostViewId != View.NO_ID && mDecor != null) { - final View needsAccessFocus = mDecor.findViewById(hostViewId); - if (needsAccessFocus != null) { - if (!tryFocusingVirtualView(needsAccessFocus, virtualViewId) - && !needsAccessFocus.requestAccessibilityFocus()) { - Log.w(TAG, "Failed to restore focus to previously accessibility" - + " focused view with id " + hostViewId); - } - } else { - Log.w(TAG, "Previously accessibility focused view reported id " + hostViewId - + " during save, but can't be found during restore."); - } - } - } - - private boolean tryFocusingVirtualView(View host, int virtualViewId) { - if (virtualViewId != AccessibilityNodeInfo.UNDEFINED_ITEM_ID) { - final AccessibilityNodeProvider nodeProvider = host.getAccessibilityNodeProvider(); - if (nodeProvider != null) { - return nodeProvider.performAction(virtualViewId, - AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS, null); - } - } - return false; - } - /** * Invoked when the panels should freeze their state. * diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java index 2a79d28a6a2b..0e07bf8c47a8 100644 --- a/core/java/com/android/internal/widget/LockPatternUtils.java +++ b/core/java/com/android/internal/widget/LockPatternUtils.java @@ -288,7 +288,6 @@ public class LockPatternUtils { public void reportFailedPasswordAttempt(int userId) { getDevicePolicyManager().reportFailedPasswordAttempt(userId); getTrustManager().reportUnlockAttempt(false /* authenticated */, userId); - requireStrongAuth(StrongAuthTracker.SOME_AUTH_REQUIRED_AFTER_WRONG_CREDENTIAL, userId); } public void reportSuccessfulPasswordAttempt(int userId) { @@ -1550,7 +1549,8 @@ public class LockPatternUtils { value = { STRONG_AUTH_NOT_REQUIRED, STRONG_AUTH_REQUIRED_AFTER_BOOT, STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW, - SOME_AUTH_REQUIRED_AFTER_USER_REQUEST}) + SOME_AUTH_REQUIRED_AFTER_USER_REQUEST, + STRONG_AUTH_REQUIRED_AFTER_LOCKOUT}) @Retention(RetentionPolicy.SOURCE) public @interface StrongAuthFlags {} @@ -1581,13 +1581,12 @@ public class LockPatternUtils { public static final int STRONG_AUTH_REQUIRED_AFTER_LOCKOUT = 0x8; /** - * Some authentication is required because the user has entered a wrong credential. + * Strong auth flags that do not prevent fingerprint from being accepted as auth. + * + * If any other flags are set, fingerprint is disabled. */ - public static final int SOME_AUTH_REQUIRED_AFTER_WRONG_CREDENTIAL = 0x10; - private static final int ALLOWING_FINGERPRINT = STRONG_AUTH_NOT_REQUIRED - | SOME_AUTH_REQUIRED_AFTER_USER_REQUEST - | SOME_AUTH_REQUIRED_AFTER_WRONG_CREDENTIAL; + | SOME_AUTH_REQUIRED_AFTER_USER_REQUEST; private final SparseIntArray mStrongAuthRequiredForUser = new SparseIntArray(); private final H mHandler; diff --git a/core/jni/android_util_Process.cpp b/core/jni/android_util_Process.cpp index 23e291f5b577..ffa710752956 100644 --- a/core/jni/android_util_Process.cpp +++ b/core/jni/android_util_Process.cpp @@ -58,21 +58,19 @@ static pthread_key_t gBgKey = -1; #endif // For both of these, err should be in the errno range (positive), not a status_t (negative) - -static void signalExceptionForPriorityError(JNIEnv* env, int err) -{ +static void signalExceptionForError(JNIEnv* env, int err, int tid) { switch (err) { case EINVAL: - jniThrowException(env, "java/lang/IllegalArgumentException", NULL); + jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException", + "Invalid argument: %d", tid); break; case ESRCH: - jniThrowException(env, "java/lang/IllegalArgumentException", "Given thread does not exist"); + jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException", + "Given thread %d does not exist", tid); break; case EPERM: - jniThrowException(env, "java/lang/SecurityException", "No permission to modify given thread"); - break; - case EACCES: - jniThrowException(env, "java/lang/SecurityException", "No permission to set to given priority"); + jniThrowExceptionFmt(env, "java/lang/SecurityException", + "No permission to modify given thread %d", tid); break; default: jniThrowException(env, "java/lang/RuntimeException", "Unknown error"); @@ -80,23 +78,27 @@ static void signalExceptionForPriorityError(JNIEnv* env, int err) } } -static void signalExceptionForGroupError(JNIEnv* env, int err) -{ +static void signalExceptionForPriorityError(JNIEnv* env, int err, int tid) { switch (err) { - case EINVAL: - jniThrowException(env, "java/lang/IllegalArgumentException", NULL); - break; - case ESRCH: - jniThrowException(env, "java/lang/IllegalArgumentException", "Given thread does not exist"); + case EACCES: + jniThrowExceptionFmt(env, "java/lang/SecurityException", + "No permission to set the priority of %d", tid); break; - case EPERM: - jniThrowException(env, "java/lang/SecurityException", "No permission to modify given thread"); + default: + signalExceptionForError(env, err, tid); break; + } + +} + +static void signalExceptionForGroupError(JNIEnv* env, int err, int tid) { + switch (err) { case EACCES: - jniThrowException(env, "java/lang/SecurityException", "No permission to set to given group"); + jniThrowExceptionFmt(env, "java/lang/SecurityException", + "No permission to set the group of %d", tid); break; default: - jniThrowException(env, "java/lang/RuntimeException", "Unknown error"); + signalExceptionForError(env, err, tid); break; } } @@ -171,7 +173,7 @@ void android_os_Process_setThreadGroup(JNIEnv* env, jobject clazz, int tid, jint SchedPolicy sp = (SchedPolicy) grp; int res = set_sched_policy(tid, sp); if (res != NO_ERROR) { - signalExceptionForGroupError(env, -res); + signalExceptionForGroupError(env, -res, tid); } } @@ -183,7 +185,7 @@ void android_os_Process_setProcessGroup(JNIEnv* env, jobject clazz, int pid, jin struct dirent *de; if ((grp == SP_FOREGROUND) || (grp > SP_MAX)) { - signalExceptionForGroupError(env, EINVAL); + signalExceptionForGroupError(env, EINVAL, pid); return; } @@ -219,7 +221,7 @@ void android_os_Process_setProcessGroup(JNIEnv* env, jobject clazz, int pid, jin if (!(d = opendir(proc_path))) { // If the process exited on us, don't generate an exception if (errno != ENOENT) - signalExceptionForGroupError(env, errno); + signalExceptionForGroupError(env, errno, pid); return; } @@ -254,7 +256,7 @@ void android_os_Process_setProcessGroup(JNIEnv* env, jobject clazz, int pid, jin #ifdef ENABLE_CPUSETS int err = set_cpuset_policy(t_pid, sp); if (err != NO_ERROR) { - signalExceptionForGroupError(env, -err); + signalExceptionForGroupError(env, -err, t_pid); break; } #endif @@ -266,14 +268,14 @@ void android_os_Process_setProcessGroup(JNIEnv* env, jobject clazz, int pid, jin // set both cpuset and cgroup for general threads err = set_cpuset_policy(t_pid, sp); if (err != NO_ERROR) { - signalExceptionForGroupError(env, -err); + signalExceptionForGroupError(env, -err, t_pid); break; } #endif err = set_sched_policy(t_pid, sp); if (err != NO_ERROR) { - signalExceptionForGroupError(env, -err); + signalExceptionForGroupError(env, -err, t_pid); break; } @@ -285,7 +287,7 @@ jint android_os_Process_getProcessGroup(JNIEnv* env, jobject clazz, jint pid) { SchedPolicy sp; if (get_sched_policy(pid, &sp) != 0) { - signalExceptionForGroupError(env, errno); + signalExceptionForGroupError(env, errno, pid); } return (int) sp; } @@ -400,7 +402,7 @@ jintArray android_os_Process_getExclusiveCores(JNIEnv* env, jobject clazz) { jintArray cpus; int pid = getpid(); if (get_sched_policy(pid, &sp) != 0) { - signalExceptionForGroupError(env, errno); + signalExceptionForGroupError(env, errno, pid); return NULL; } get_exclusive_cpuset_cores(sp, &cpu_set); @@ -449,10 +451,10 @@ jint android_os_Process_getThreadScheduler(JNIEnv* env, jclass clazz, errno = 0; policy = sched_getscheduler(tid); if (errno != 0) { - signalExceptionForPriorityError(env, errno); + signalExceptionForPriorityError(env, errno, tid); } #else - signalExceptionForPriorityError(env, ENOSYS); + signalExceptionForPriorityError(env, ENOSYS, tid); #endif return policy; } @@ -466,10 +468,10 @@ void android_os_Process_setThreadScheduler(JNIEnv* env, jclass clazz, param.sched_priority = pri; int rc = sched_setscheduler(tid, policy, ¶m); if (rc) { - signalExceptionForPriorityError(env, errno); + signalExceptionForPriorityError(env, errno, tid); } #else - signalExceptionForPriorityError(env, ENOSYS); + signalExceptionForPriorityError(env, ENOSYS, tid); #endif } @@ -494,9 +496,9 @@ void android_os_Process_setThreadPriority(JNIEnv* env, jobject clazz, int rc = androidSetThreadPriority(pid, pri); if (rc != 0) { if (rc == INVALID_OPERATION) { - signalExceptionForPriorityError(env, errno); + signalExceptionForPriorityError(env, errno, pid); } else { - signalExceptionForGroupError(env, errno); + signalExceptionForGroupError(env, errno, pid); } } @@ -516,7 +518,7 @@ jint android_os_Process_getThreadPriority(JNIEnv* env, jobject clazz, errno = 0; jint pri = getpriority(PRIO_PROCESS, pid); if (errno != 0) { - signalExceptionForPriorityError(env, errno); + signalExceptionForPriorityError(env, errno, pid); } //ALOGI("Returning priority of %" PRId32 ": %" PRId32 "\n", pid, pri); return pri; diff --git a/core/res/res/drawable/ic_lock_power_off.xml b/core/res/res/drawable/ic_lock_power_off.xml index 718f17ed0c19..babd1be220cb 100644 --- a/core/res/res/drawable/ic_lock_power_off.xml +++ b/core/res/res/drawable/ic_lock_power_off.xml @@ -1,19 +1,25 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- 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. - You may obtain a copy of the License at + 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 + 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. + 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. --> - -<bitmap xmlns:android="http://schemas.android.com/apk/res/android" - android:src="@drawable/ic_lock_power_off_alpha" - android:tint="?attr/colorControlNormal" /> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24.0dp" + android:height="24.0dp" + android:viewportHeight="24.0" + android:viewportWidth="24.0" + android:tint="?attr/colorControlNormal"> + <path + android:fillColor="#FF000000" + android:pathData="M13.0,3.0l-2.0,0.0l0.0,10.0l2.0,0.0L13.0,3.0zm4.83,2.17l-1.42,1.42C17.99,7.86 19.0,9.81 19.0,12.0c0.0,3.87 -3.13,7.0 -7.0,7.0s-7.0,-3.13 -7.0,-7.0c0.0,-2.19 1.01,-4.14 2.58,-5.42L6.17,5.17C4.23,6.82 3.0,9.26 3.0,12.0c0.0,4.97 4.03,9.0 9.0,9.0s9.0,-4.03 9.0,-9.0c0.0,-2.74 -1.23,-5.18 -3.17,-6.83z"/> +</vector> diff --git a/core/res/res/drawable/ic_restart.xml b/core/res/res/drawable/ic_restart.xml new file mode 100644 index 000000000000..47ac483fa311 --- /dev/null +++ b/core/res/res/drawable/ic_restart.xml @@ -0,0 +1,28 @@ +<!-- + 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="24.0dp" + android:height="24.0dp" + android:viewportHeight="24.0" + android:viewportWidth="24.0" + android:tint="?attr/colorControlNormal"> + <path + android:fillColor="#FF000000" + android:pathData="M12.0,4.0L12.0,1.0L8.0,5.0l4.0,4.0L12.0,6.0c3.9,0.0 7.0,3.1 7.0,7.0c0.0,3.9 -3.1,7.0 -7.0,7.0l0.0,2.0c5.0,0.0 9.0,-4.0 9.0,-9.0C21.0,8.0 17.0,4.0 12.0,4.0z"/> + <path + android:fillColor="#FF000000" + android:pathData="M5.0,12.9C5.0,11.0 5.8,9.2 7.2,7.9L5.8,6.4C4.0,8.1 3.0,10.5 3.0,12.9c0.0,4.0 2.7,7.6 6.5,8.7l0.5,-1.9C7.1,18.8 5.0,16.1 5.0,12.9z"/> +</vector> diff --git a/core/res/res/layout/chooser_grid.xml b/core/res/res/layout/chooser_grid.xml index d12c8ba2f2ef..d8dd447e6a74 100644 --- a/core/res/res/layout/chooser_grid.xml +++ b/core/res/res/layout/chooser_grid.xml @@ -41,7 +41,7 @@ android:visibility="gone" style="?attr/borderlessButtonStyle" android:textAppearance="?attr/textAppearanceButton" - android:textColor="@color/material_deep_teal_500" + android:textColor="?attr/colorAccent" android:gravity="center_vertical" android:layout_alignParentTop="true" android:layout_alignParentRight="true" diff --git a/core/res/res/layout/resolver_list.xml b/core/res/res/layout/resolver_list.xml index ae945031f11d..c4e8e9cb63bf 100644 --- a/core/res/res/layout/resolver_list.xml +++ b/core/res/res/layout/resolver_list.xml @@ -42,7 +42,7 @@ android:visibility="gone" style="?attr/borderlessButtonStyle" android:textAppearance="?attr/textAppearanceButton" - android:textColor="@color/material_deep_teal_500" + android:textColor="?attr/colorAccent" android:gravity="center_vertical" android:layout_alignParentTop="true" android:layout_alignParentRight="true" diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index d15b1750c8bf..6161494353f2 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -539,9 +539,12 @@ Software implementation will be used if config_hardware_auto_brightness_available is not set --> <bool name="config_automatic_brightness_available">false</bool> - <!-- Fast brightness animation ramp rate --> + <!-- Fast brightness animation ramp rate in brightness units per second--> <integer translatable="false" name="config_brightness_ramp_rate_fast">200</integer> + <!-- Slow brightness animation ramp rate in brightness units per second--> + <integer translatable="false" name="config_brightness_ramp_rate_slow">40</integer> + <!-- Don't name config resources like this. It should look like config_annoyDianne --> <bool name="config_annoy_dianne">true</bool> @@ -2088,9 +2091,11 @@ "bugreport" = Take bug report, if available "silent" = silent mode "users" = list of users + "restart" = restart device --> <string-array translatable="false" name="config_globalActionsList"> <item>power</item> + <item>restart</item> <item>bugreport</item> <item>users</item> </string-array> @@ -2517,6 +2522,10 @@ <!-- Flag indicating whether round icons should be parsed from the application manifest. --> <bool name="config_useRoundIcon">false</bool> + <!-- Flag indicating whether the assist disclosure can be disabled using + ASSIST_DISCLOSURE_ENABLED. --> + <bool name="config_allowDisablingAssistDisclosure">false</bool> + <!-- True if the device supports system navigation keys. --> <bool name="config_supportSystemNavigationKeys">false</bool> diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index 5a9099b8bf6a..c4594e5bdfe7 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -484,6 +484,10 @@ <!-- label for item that turns off power in phone options dialog --> <string name="global_action_power_off">Power off</string> + <!-- label for item that restarts phone in phone options dialog --> + <!-- TODO: promote to separate string--> + <string name="global_action_restart" translatable="false">@string/sim_restart_button</string> + <!-- label for item that generates a bug report in the phone options dialog --> <string name="global_action_bug_report">Bug report</string> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 384e98503cde..3c2b55b033b9 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -1593,6 +1593,7 @@ <java-symbol type="string" name="bugreport_title" /> <java-symbol type="string" name="faceunlock_multiple_failures" /> <java-symbol type="string" name="global_action_power_off" /> + <java-symbol type="string" name="global_action_restart" /> <java-symbol type="string" name="global_actions_airplane_mode_off_status" /> <java-symbol type="string" name="global_actions_airplane_mode_on_status" /> <java-symbol type="string" name="global_actions_toggle_airplane_mode" /> @@ -1760,6 +1761,7 @@ <java-symbol type="integer" name="config_undockedHdmiRotation" /> <java-symbol type="integer" name="config_virtualKeyQuietTimeMillis" /> <java-symbol type="integer" name="config_brightness_ramp_rate_fast" /> + <java-symbol type="integer" name="config_brightness_ramp_rate_slow" /> <java-symbol type="layout" name="am_compat_mode_dialog" /> <java-symbol type="layout" name="launch_warning" /> <java-symbol type="layout" name="safe_mode" /> @@ -2682,6 +2684,7 @@ <java-symbol type="drawable" name="ic_doc_generic" /> <java-symbol type="bool" name="config_nightDisplayAvailable" /> + <java-symbol type="bool" name="config_allowDisablingAssistDisclosure" /> <java-symbol type="integer" name="config_defaultNightDisplayAutoMode" /> <java-symbol type="integer" name="config_defaultNightDisplayCustomStartTime" /> <java-symbol type="integer" name="config_defaultNightDisplayCustomEndTime" /> @@ -2691,4 +2694,7 @@ <java-symbol type="bool" name="config_permissionReviewRequired" /> + + <java-symbol type="drawable" name="ic_restart" /> + </resources> diff --git a/core/tests/coretests/src/android/widget/TextViewTest.java b/core/tests/coretests/src/android/widget/TextViewTest.java index 522149941416..3ccbf17c815e 100644 --- a/core/tests/coretests/src/android/widget/TextViewTest.java +++ b/core/tests/coretests/src/android/widget/TextViewTest.java @@ -29,6 +29,7 @@ import android.text.Spannable; * TextViewTest tests {@link TextView}. */ public class TextViewTest extends ActivityInstrumentationTestCase2<TextViewActivity> { + private TextView mTextView; public TextViewTest() { super(TextViewActivity.class); @@ -37,16 +38,22 @@ public class TextViewTest extends ActivityInstrumentationTestCase2<TextViewActiv @SmallTest @Presubmit public void testArray() throws Exception { - TextView tv = new TextView(getActivity()); + getActivity().runOnUiThread(new Runnable() { + @Override + public void run() { + mTextView = new TextView(getActivity()); + } + }); + getInstrumentation().waitForIdleSync(); char[] c = new char[] { 'H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd', '!' }; - tv.setText(c, 1, 4); - CharSequence oldText = tv.getText(); + mTextView.setText(c, 1, 4); + CharSequence oldText = mTextView.getText(); - tv.setText(c, 4, 5); - CharSequence newText = tv.getText(); + mTextView.setText(c, 4, 5); + CharSequence newText = mTextView.getText(); assertTrue(newText == oldText); @@ -67,12 +74,18 @@ public class TextViewTest extends ActivityInstrumentationTestCase2<TextViewActiv @SmallTest public void testProcessTextActivityResultNonEditable() { - final TextView tv = new TextView(getActivity()); + getActivity().runOnUiThread(new Runnable() { + @Override + public void run() { + mTextView = new TextView(getActivity()); + } + }); + getInstrumentation().waitForIdleSync(); CharSequence originalText = "This is some text."; - tv.setText(originalText, TextView.BufferType.SPANNABLE); - assertEquals(originalText, tv.getText().toString()); - tv.setTextIsSelectable(true); - Selection.setSelection((Spannable) tv.getText(), 0, tv.getText().length()); + mTextView.setText(originalText, TextView.BufferType.SPANNABLE); + assertEquals(originalText, mTextView.getText().toString()); + mTextView.setTextIsSelectable(true); + Selection.setSelection((Spannable) mTextView.getText(), 0, mTextView.getText().length()); // We need to run this in the UI thread, as it will create a Toast. getActivity().runOnUiThread(new Runnable() { @@ -81,60 +94,79 @@ public class TextViewTest extends ActivityInstrumentationTestCase2<TextViewActiv CharSequence newText = "Text is replaced."; Intent data = new Intent(); data.putExtra(Intent.EXTRA_PROCESS_TEXT, newText); - tv.onActivityResult(TextView.PROCESS_TEXT_REQUEST_CODE, Activity.RESULT_OK, data); + mTextView.onActivityResult(TextView.PROCESS_TEXT_REQUEST_CODE, Activity.RESULT_OK, data); } }); getInstrumentation().waitForIdleSync(); // This is a TextView, which can't be modified. Hence no change should have been made. - assertEquals(originalText, tv.getText().toString()); + assertEquals(originalText, mTextView.getText().toString()); } @SmallTest public void testProcessTextActivityResultEditable() { - EditText tv = new EditText(getActivity()); + getActivity().runOnUiThread(new Runnable() { + @Override + public void run() { + mTextView = new EditText(getActivity()); + } + }); + getInstrumentation().waitForIdleSync(); CharSequence originalText = "This is some text."; - tv.setText(originalText, TextView.BufferType.SPANNABLE); - assertEquals(originalText, tv.getText().toString()); - tv.setTextIsSelectable(true); - Selection.setSelection(tv.getText(), 0, tv.getText().length()); + mTextView.setText(originalText, TextView.BufferType.SPANNABLE); + assertEquals(originalText, mTextView.getText().toString()); + mTextView.setTextIsSelectable(true); + Selection.setSelection(((EditText) mTextView).getText(), 0, mTextView.getText().length()); CharSequence newText = "Text is replaced."; Intent data = new Intent(); data.putExtra(Intent.EXTRA_PROCESS_TEXT, newText); - tv.onActivityResult(TextView.PROCESS_TEXT_REQUEST_CODE, Activity.RESULT_OK, data); + mTextView.onActivityResult(TextView.PROCESS_TEXT_REQUEST_CODE, Activity.RESULT_OK, data); - assertEquals(newText, tv.getText().toString()); + assertEquals(newText, mTextView.getText().toString()); } @SmallTest public void testProcessTextActivityResultCancel() { - EditText tv = new EditText(getActivity()); + getActivity().runOnUiThread(new Runnable() { + @Override + public void run() { + mTextView = new EditText(getActivity()); + } + }); + getInstrumentation().waitForIdleSync(); CharSequence originalText = "This is some text."; - tv.setText(originalText, TextView.BufferType.SPANNABLE); - assertEquals(originalText, tv.getText().toString()); - tv.setTextIsSelectable(true); - Selection.setSelection(tv.getText(), 0, tv.getText().length()); + mTextView.setText(originalText, TextView.BufferType.SPANNABLE); + assertEquals(originalText, mTextView.getText().toString()); + mTextView.setTextIsSelectable(true); + Selection.setSelection(((EditText) mTextView).getText(), 0, mTextView.getText().length()); CharSequence newText = "Text is replaced."; Intent data = new Intent(); data.putExtra(Intent.EXTRA_PROCESS_TEXT, newText); - tv.onActivityResult(TextView.PROCESS_TEXT_REQUEST_CODE, Activity.RESULT_CANCELED, data); + mTextView.onActivityResult(TextView.PROCESS_TEXT_REQUEST_CODE, Activity.RESULT_CANCELED, + data); - assertEquals(originalText, tv.getText().toString()); + assertEquals(originalText, mTextView.getText().toString()); } @SmallTest public void testProcessTextActivityNoData() { - EditText tv = new EditText(getActivity()); + getActivity().runOnUiThread(new Runnable() { + @Override + public void run() { + mTextView = new EditText(getActivity()); + } + }); + getInstrumentation().waitForIdleSync(); CharSequence originalText = "This is some text."; - tv.setText(originalText, TextView.BufferType.SPANNABLE); - assertEquals(originalText, tv.getText().toString()); - tv.setTextIsSelectable(true); - Selection.setSelection(tv.getText(), 0, tv.getText().length()); + mTextView.setText(originalText, TextView.BufferType.SPANNABLE); + assertEquals(originalText, mTextView.getText().toString()); + mTextView.setTextIsSelectable(true); + Selection.setSelection(((EditText) mTextView).getText(), 0, mTextView.getText().length()); - tv.onActivityResult(TextView.PROCESS_TEXT_REQUEST_CODE, Activity.RESULT_OK, null); + mTextView.onActivityResult(TextView.PROCESS_TEXT_REQUEST_CODE, Activity.RESULT_OK, null); - assertEquals(originalText, tv.getText().toString()); + assertEquals(originalText, mTextView.getText().toString()); } } diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsSamplingTimerTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsSamplingTimerTest.java index ce6879d0ef4e..b4afddab97c9 100644 --- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsSamplingTimerTest.java +++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsSamplingTimerTest.java @@ -178,19 +178,40 @@ public class BatteryStatsSamplingTimerTest extends TestCase { clocks.elapsedRealtime() * 1000); offBatterySummaryParcel.setDataPosition(0); + // Set the timebase running again. That way any issues with tracking reported values + // get tested when we unparcel the timers below. + timeBase.setRunning(true, clocks.uptimeMillis(), clocks.elapsedRealtime()); + // Read the on battery summary from the parcel. - BatteryStatsImpl.SamplingTimer unparceledTimer = new BatteryStatsImpl.SamplingTimer( - clocks, timeBase); - unparceledTimer.readSummaryFromParcelLocked(onBatterySummaryParcel); + BatteryStatsImpl.SamplingTimer unparceledOnBatteryTimer = + new BatteryStatsImpl.SamplingTimer(clocks, timeBase); + unparceledOnBatteryTimer.readSummaryFromParcelLocked(onBatterySummaryParcel); - assertEquals(10, unparceledTimer.getTotalTimeLocked(0, BatteryStats.STATS_SINCE_CHARGED)); - assertEquals(1, unparceledTimer.getCountLocked(BatteryStats.STATS_SINCE_CHARGED)); + assertEquals(10, unparceledOnBatteryTimer.getTotalTimeLocked(0, + BatteryStats.STATS_SINCE_CHARGED)); + assertEquals(1, unparceledOnBatteryTimer.getCountLocked(BatteryStats.STATS_SINCE_CHARGED)); // Read the off battery summary from the parcel. - unparceledTimer = new BatteryStatsImpl.SamplingTimer(clocks, timeBase); - unparceledTimer.readSummaryFromParcelLocked(offBatterySummaryParcel); + BatteryStatsImpl.SamplingTimer unparceledOffBatteryTimer = + new BatteryStatsImpl.SamplingTimer(clocks, timeBase); + unparceledOffBatteryTimer.readSummaryFromParcelLocked(offBatterySummaryParcel); + + assertEquals(10, unparceledOffBatteryTimer.getTotalTimeLocked(0, + BatteryStats.STATS_SINCE_CHARGED)); + assertEquals(1, unparceledOffBatteryTimer.getCountLocked(BatteryStats.STATS_SINCE_CHARGED)); - assertEquals(10, unparceledTimer.getTotalTimeLocked(0, BatteryStats.STATS_SINCE_CHARGED)); - assertEquals(1, unparceledTimer.getCountLocked(BatteryStats.STATS_SINCE_CHARGED)); + // Now, just like with a fresh timer, the first update should be absorbed to account for + // data being collected when we weren't recording. + unparceledOnBatteryTimer.update(10, 10); + + assertEquals(10, unparceledOnBatteryTimer.getTotalTimeLocked(0, + BatteryStats.STATS_SINCE_CHARGED)); + assertEquals(1, unparceledOnBatteryTimer.getCountLocked(BatteryStats.STATS_SINCE_CHARGED)); + + unparceledOffBatteryTimer.update(10, 10); + + assertEquals(10, unparceledOffBatteryTimer.getTotalTimeLocked(0, + BatteryStats.STATS_SINCE_CHARGED)); + assertEquals(1, unparceledOffBatteryTimer.getCountLocked(BatteryStats.STATS_SINCE_CHARGED)); } } diff --git a/docs/html/guide/topics/renderscript/compute.jd b/docs/html/guide/topics/renderscript/compute.jd index fe686547fe6c..13880ec6b796 100755 --- a/docs/html/guide/topics/renderscript/compute.jd +++ b/docs/html/guide/topics/renderscript/compute.jd @@ -16,6 +16,13 @@ parent.link=index.html </ol> </li> <li><a href="#using-rs-from-java">Using RenderScript from Java Code</a></li> + <li><a href="#reduction-in-depth">Reduction Kernels in Depth</a> + <ol> + <li><a href="#writing-reduction-kernel">Writing a reduction kernel</a></li> + <li><a href="#calling-reduction-kernel">Calling a reduction kernel from Java code</a></li> + <li><a href="#more-example">More example reduction kernels</a></li> + </ol> + </li> </ol> <h2>Related Samples</h2> @@ -29,16 +36,18 @@ parent.link=index.html <p>RenderScript is a framework for running computationally intensive tasks at high performance on Android. RenderScript is primarily oriented for use with data-parallel computation, although serial -computationally intensive workloads can benefit as well. The RenderScript runtime will parallelize -work across all processors available on a device, such as multi-core CPUs, GPUs, or DSPs, allowing -you to focus on expressing algorithms rather than scheduling work or load balancing. RenderScript is +workloads can benefit as well. The RenderScript runtime parallelizes +work across processors available on a device, such as multi-core CPUs and GPUs. This allows +you to focus on expressing algorithms rather than scheduling work. RenderScript is especially useful for applications performing image processing, computational photography, or computer vision.</p> <p>To begin with RenderScript, there are two main concepts you should understand:</p> <ul> -<li>High-performance compute kernels are written in a C99-derived language.</li> +<li>High-performance compute kernels are written in a C99-derived language. A <i>compute + kernel</i> is a function or collection of functions that you can direct the RenderScript runtime + to execute in parallel across a collection of data.</li> <li>A Java API is used for managing the lifetime of RenderScript resources and controlling kernel execution.</li> @@ -48,7 +57,7 @@ execution.</li> <p>A RenderScript kernel typically resides in a <code>.rs</code> file in the <code><project_root>/src/</code> directory; each <code>.rs</code> file is called a -script. Every script contains its own set of kernels, functions, and variables. A script can +<i>script</i>. Every script contains its own set of kernels, functions, and variables. A script can contain:</p> <ul> @@ -57,23 +66,32 @@ RenderScript kernel language used in this script. Currently, 1 is the only valid <li>A pragma declaration (<code>#pragma rs java_package_name(com.example.app)</code>) that declares the package name of the Java classes reflected from this script. -Note that your .rs file must be part of your application package, and not in a +Note that your <code>.rs</code> file must be part of your application package, and not in a library project.</li> -<li>Some number of invokable functions. An invokable function is a single-threaded RenderScript +<li>Zero or more <strong><i>invokable functions</i></strong>. An invokable function is a single-threaded RenderScript function that you can call from your Java code with arbitrary arguments. These are often useful for initial setup or serial computations within a larger processing pipeline.</li> -<li>Some number of script globals. A script global is equivalent to a global variable in C. You can +<li><p>Zero or more <strong><i>script globals</i></strong>. A script global is equivalent to a global variable in C. You can access script globals from Java code, and these are often used for parameter passing to RenderScript -kernels.</li> +kernels.</p></li> -<li>Some number of compute kernels. A kernel is a parallel function that executes across every -{@link android.renderscript.Element} within an {@link android.renderscript.Allocation}. +<li><p>Zero or more <strong><i>compute kernels</i></strong>. There are two kinds of compute +kernels: <i>mapping</i> kernels (also called <i>foreach</i> kernels) +and <i>reduction</i> kernels.</p> -<p>A simple kernel may look like the following:</p> +<p>A <em>mapping kernel</em> is a parallel function that operates on a collection of {@link + android.renderscript.Allocation Allocations} of the same dimensions. By default, it executes + once for every coordinate in those dimensions. It is typically (but not exclusively) used to + transform a collection of input {@link android.renderscript.Allocation Allocations} to an + output {@link android.renderscript.Allocation} one {@link android.renderscript.Element} at a + time.</p> -<pre>uchar4 __attribute__((kernel)) invert(uchar4 in, uint32_t x, uint32_t y) { +<ul> +<li><p>Here is an example of a simple <strong>mapping kernel</strong>:</p> + +<pre>uchar4 RS_KERNEL invert(uchar4 in, uint32_t x, uint32_t y) { uchar4 out = in; out.r = 255 - in.r; out.g = 255 - in.g; @@ -81,40 +99,113 @@ kernels.</li> return out; }</pre> -<p>In most respects, this is identical to a standard C function. The first notable feature is the -<code>__attribute__((kernel))</code> applied to the function prototype. This denotes that the -function is a RenderScript kernel instead of an invokable function. The next feature is the -<code>in</code> argument and its type. In a RenderScript kernel, this is a special argument that is -automatically filled in based on the input {@link android.renderscript.Allocation} passed to the -kernel launch. By default, the kernel is run across an entire {@link -android.renderscript.Allocation}, with one execution of the kernel body per {@link -android.renderscript.Element} in the {@link android.renderscript.Allocation}. The third notable -feature is the return type of the kernel. The value returned from the kernel is automatically -written to the appropriate location in the output {@link android.renderscript.Allocation}. The -RenderScript runtime checks to ensure that the {@link android.renderscript.Element} types of the -input and output Allocations match the kernel's prototype; if they do not match, an exception is -thrown.</p> - -<p>A kernel may have an input {@link android.renderscript.Allocation}, an output {@link -android.renderscript.Allocation}, or both. A kernel may not have more than one input or one output -{@link android.renderscript.Allocation}. If more than one input or output is required, those objects -should be bound to <code>rs_allocation</code> script globals and accessed from a kernel or invokable -function via <code>rsGetElementAt_<em>type</em>()</code> or -<code>rsSetElementAt_<em>type</em>()</code>.</p> - -<p>A kernel may access the coordinates of the current execution using the <code>x</code>, -<code>y</code>, and <code>z</code> arguments. These arguments are optional, but the type of the -coordinate arguments must be <code>uint32_t</code>.</p></li> +<p>In most respects, this is identical to a standard C + function. The <a href="#RS_KERNEL"><code>RS_KERNEL</code></a> property applied to the + function prototype specifies that the function is a RenderScript mapping kernel instead of an + invokable function. The <code>in</code> argument is automatically filled in based on the + input {@link android.renderscript.Allocation} passed to the kernel launch. The + arguments <code>x</code> and <code>y</code> are + discussed <a href="#special-arguments">below</a>. The value returned from the kernel is + automatically written to the appropriate location in the output {@link + android.renderscript.Allocation}. By default, this kernel is run across its entire input + {@link android.renderscript.Allocation}, with one execution of the kernel function per {@link + android.renderscript.Element} in the {@link android.renderscript.Allocation}.</p> + +<p>A mapping kernel may have one or more input {@link android.renderscript.Allocation + Allocations}, a single output {@link android.renderscript.Allocation}, or both. The + RenderScript runtime checks to ensure that all input and output Allocations have the same + dimensions, and that the {@link android.renderscript.Element} types of the input and output + Allocations match the kernel's prototype; if either of these checks fails, RenderScript + throws an exception.</p> + +<p class="note"><strong>NOTE:</strong> Before Android 6.0 (API level 23), a mapping kernel may + not have more than one input {@link android.renderscript.Allocation}.</p> + +<p>If you need more input or output {@link android.renderscript.Allocation Allocations} than + the kernel has, those objects should be bound to <code>rs_allocation</code> script globals + and accessed from a kernel or invokable function + via <code>rsGetElementAt_<i>type</i>()</code> or <code>rsSetElementAt_<i>type</i>()</code>.</p> + +<p><strong>NOTE:</strong> <a id="RS_KERNEL"><code>RS_KERNEL</code></a> is a macro + defined automatically by RenderScript for your convenience:</p> +<pre> +#define RS_KERNEL __attribute__((kernel)) +</pre> +</li> +</ul> + +<p>A <em>reduction kernel</em> is a family of functions that operates on a collection of input + {@link android.renderscript.Allocation Allocations} of the same dimensions. By default, + its <a href="#accumulator-function">accumulator function</a> executes once for every + coordinate in those dimensions. It is typically (but not exclusively) used to "reduce" a + collection of input {@link android.renderscript.Allocation Allocations} to a single + value.</p> + +<ul> +<li><p>Here is an <a id="example-addint">example</a> of a simple <strong>reduction +kernel</strong> that adds up the {@link android.renderscript.Element Elements} of its +input:</p> + +<pre>#pragma rs reduce(addint) accumulator(addintAccum) + +static void addintAccum(int *accum, int val) { + *accum += val; +}</pre> + +<p>A reduction kernel consists of one or more user-written functions. +<code>#pragma rs reduce</code> is used to define the kernel by specifying its name +(<code>addint</code>, in this example) and the names and roles of the functions that make +up the kernel (an <code>accumulator</code> function <code>addintAccum</code>, in this +example). All such functions must be <code>static</code>. A reduction kernel always +requires an <code>accumulator</code> function; it may also have other functions, depending +on what you want the kernel to do.</p> + +<p>A reduction kernel accumulator function must return <code>void</code> and must have at least +two arguments. The first argument (<code>accum</code>, in this example) is a pointer to +an <i>accumulator data item</i> and the second (<code>val</code>, in this example) is +automatically filled in based on the input {@link android.renderscript.Allocation} passed to +the kernel launch. The accumulator data item is created by the RenderScript runtime; by +default, it is initialized to zero. By default, this kernel is run across its entire input +{@link android.renderscript.Allocation}, with one execution of the accumulator function per +{@link android.renderscript.Element} in the {@link android.renderscript.Allocation}. By +default, the final value of the accumulator data item is treated as the result of the +reduction, and is returned to Java. The RenderScript runtime checks to ensure that the {@link +android.renderscript.Element} type of the input Allocation matches the accumulator function's +prototype; if it does not match, RenderScript throws an exception.</p> + +<p>A reduction kernel has one or more input {@link android.renderscript.Allocation +Allocations} but no output {@link android.renderscript.Allocation Allocations}.</p></li> + +<p>Reduction kernels are explained in more detail <a href="#reduction-in-depth">here</a>.</p> + +<p>Reduction kernels are supported in Android 7.0 (API level 24) and later.</p> +</li> +</ul> + +<p>A mapping kernel function or a reduction kernel accumulator function may access the coordinates +of the current execution using the <a id="special-arguments">special arguments</a> <code>x</code>, +<code>y</code>, and <code>z</code>, which must be of type <code>int</code> or <code>uint32_t</code>. +These arguments are optional.</p> + +<p>A mapping kernel function or a reduction kernel accumulator +function may also take the optional special argument +<code>context</code> of type <a +href='reference/rs_for_each.html#android_rs:rs_kernel_context'>rs_kernel_context</a>. +It is needed by a family of runtime APIs that are used to query +certain properties of the current execution -- for example, <a +href='reference/rs_for_each.html#android_rs:rsGetDimX'>rsGetDimX</a>. +(The <code>context</code> argument is available in Android 6.0 (API level 23) and later.)</p> +</li> <li>An optional <code>init()</code> function. An <code>init()</code> function is a special type of -invokable function that is run when the script is first instantiated. This allows for some +invokable function that RenderScript runs when the script is first instantiated. This allows for some computation to occur automatically at script creation.</li> -<li>Some number of static script globals and functions. A static script global is equivalent to a -script global except that it cannot be set from Java code. A static function is a standard C +<li>Zero or more <strong><i>static script globals and functions</i></strong>. A static script global is equivalent to a +script global except that it cannot be accessed from Java code. A static function is a standard C function that can be called from any kernel or invokable function in the script but is not exposed to the Java API. If a script global or function does not need to be called from Java code, it is -highly recommended that those be declared <code>static</code>.</li> </ul> +highly recommended that it be declared <code>static</code>.</li> </ul> <h4>Setting floating point precision</h4> @@ -129,13 +220,13 @@ different level of floating point precision:</p> </li> - <li><code>#pragma rs_fp_relaxed</code> - For apps that don’t require strict IEEE 754-2008 + <li><code>#pragma rs_fp_relaxed</code>: For apps that don’t require strict IEEE 754-2008 compliance and can tolerate less precision. This mode enables flush-to-zero for denorms and round-towards-zero. </li> - <li><code>#pragma rs_fp_imprecise</code> - For apps that don’t have stringent precision + <li><code>#pragma rs_fp_imprecise</code>: For apps that don’t have stringent precision requirements. This mode enables everything in <code>rs_fp_relaxed</code> along with the following: @@ -162,14 +253,21 @@ precision (such as SIMD CPU instructions).</p> available on devices running Android 3.0 (API level 11) and higher. </li> <li><strong>{@link android.support.v8.renderscript}</strong> - The APIs in this package are available through a <a href="{@docRoot}tools/support-library/features.html#v8">Support - Library</a>, which allows you to use them on devices running Android 2.2 (API level 8) and + Library</a>, which allows you to use them on devices running Android 2.3 (API level 9) and higher.</li> </ul> -<p>We strongly recommend using the Support Library APIs for accessing RenderScript because they - provide a wider range of device compatibility. Developers targeting specific versions of - Android can use {@link android.renderscript} if necessary.</p> +<p>Here are the tradeoffs:</p> +<ul> +<li>If you use the Support Library APIs, the RenderScript portion of your application will be + compatible with devices running Android 2.3 (API level 9) and higher, regardless of which RenderScript + features you use. This allows your application to work on more devices than if you use the + native (<strong>{@link android.renderscript}</strong>) APIs.</li> +<li>Certain RenderScript features are not available through the Support Library APIs.</li> +<li>If you use the Support Library APIs, you will get (possibly significantly) larger APKs than +if you use the native (<strong>{@link android.renderscript}</strong>) APIs.</li> +</ul> <h3 id="ide-setup">Using the RenderScript Support Library APIs</h3> @@ -202,7 +300,7 @@ android { buildToolsVersion "23.0.3" defaultConfig { - minSdkVersion 8 + minSdkVersion 9 targetSdkVersion 19 <strong> renderscriptTargetApi 18 @@ -250,7 +348,7 @@ import android.support.v8.renderscript.*; <p>Using RenderScript from Java code relies on the API classes located in the {@link android.renderscript} or the {@link android.support.v8.renderscript} package. Most -applications follow the same basic usage patterns:</p> +applications follow the same basic usage pattern:</p> <ol> @@ -266,12 +364,12 @@ possible. Typically, an application will have only a single RenderScript context script.</strong> An {@link android.renderscript.Allocation} is a RenderScript object that provides storage for a fixed amount of data. Kernels in scripts take {@link android.renderscript.Allocation} objects as their input and output, and {@link android.renderscript.Allocation} objects can be -accessed in kernels using <code>rsGetElementAt_<em>type</em>()</code> and -<code>rsSetElementAt_<em>type</em>()</code> when bound as script globals. {@link +accessed in kernels using <code>rsGetElementAt_<i>type</i>()</code> and +<code>rsSetElementAt_<i>type</i>()</code> when bound as script globals. {@link android.renderscript.Allocation} objects allow arrays to be passed from Java code to RenderScript code and vice-versa. {@link android.renderscript.Allocation} objects are typically created using -{@link android.renderscript.Allocation#createTyped} or {@link -android.renderscript.Allocation#createFromBitmap}.</li> +{@link android.renderscript.Allocation#createTyped createTyped()} or {@link +android.renderscript.Allocation#createFromBitmap createFromBitmap()}.</li> <li><strong>Create whatever scripts are necessary.</strong> There are two types of scripts available to you when using RenderScript: @@ -281,9 +379,9 @@ to you when using RenderScript: <li><strong>ScriptC</strong>: These are the user-defined scripts as described in <a href="#writing-an-rs-kernel">Writing a RenderScript Kernel</a> above. Every script has a Java class reflected by the RenderScript compiler in order to make it easy to access the script from Java code; -this class will have the name <code>ScriptC_<em>filename</em></code>. For example, if the kernel -above was located in <code>invert.rs</code> and a RenderScript context was already located in -<code>mRS</code>, the Java code to instantiate the script would be: +this class has the name <code>ScriptC_<i>filename</i></code>. For example, if the mapping kernel +above were located in <code>invert.rs</code> and a RenderScript context were already located in +<code>mRenderScript</code>, the Java code to instantiate the script would be: <pre>ScriptC_invert invert = new ScriptC_invert(mRenderScript);</pre></li> @@ -294,35 +392,926 @@ such as Gaussian blur, convolution, and image blending. For more information, se </ul></li> <li><strong>Populate Allocations with data.</strong> Except for Allocations created with {@link -android.renderscript.Allocation#createFromBitmap}, an Allocation will be populated with empty data when it is -first created. To populate an Allocation, use one of the <code>copy</code> methods in {@link -android.renderscript.Allocation}.</li> - -<li><strong>Set any necessary script globals.</strong> Globals may be set using methods in the same -<code>ScriptC_<em>filename</em></code> class with methods named -<code>set_<em>globalname</em></code>. For example, in order to set an <code>int</code> named -<code>elements</code>, use the Java method <code>set_elements(int)</code>. RenderScript objects can -also be set in kernels; for example, the <code>rs_allocation</code> variable named -<code>lookup</code> can be set with the method <code>set_lookup(Allocation)</code>.</li> - -<li><strong>Launch the appropriate kernels.</strong> Methods to launch a given kernel will be -reflected in the same <code>ScriptC_<em>filename</em></code> class with methods named -<code>forEach_<em>kernelname</em>()</code>. These launches are asynchronous, and launches will be -serialized in the order in which they are launched. Depending on the arguments to the kernel, the -method will take either one or two Allocations. By default, a kernel will execute over the entire -input or output Allocation; to execute over a subset of that Allocation, pass an appropriate {@link -android.renderscript.Script.LaunchOptions} as the last argument to the <code>forEach</code> method. - -<p>Invoked functions can be launched using the <code>invoke_<em>functionname</em></code> methods -reflected in the same <code>ScriptC_<em>filename</em></code> class.</p></li> - -<li><strong>Copy data out of {@link android.renderscript.Allocation} objects.</strong> In order to -access data from an {@link android.renderscript.Allocation} from Java code, that data must be copied -back to Java buffers using one of the <code>copy</code> methods in {@link -android.renderscript.Allocation}. These functions will synchronize with asynchronous kernel and -function launches as necessary.</li> - -<li><strong>Tear down the RenderScript context.</strong> The RenderScript context can be destroyed +android.renderscript.Allocation#createFromBitmap createFromBitmap()}, an Allocation is populated with empty data when it is +first created. To populate an Allocation, use one of the "copy" methods in {@link +android.renderscript.Allocation}. The "copy" methods are <a href="#asynchronous-model">synchronous</a>.</li> + +<li><strong>Set any necessary script globals.</strong> You may set globals using methods in the + same <code>ScriptC_<i>filename</i></code> class named <code>set_<i>globalname</i></code>. For + example, in order to set an <code>int</code> variable named <code>threshold</code>, use the + Java method <code>set_threshold(int)</code>; and in order to set + an <code>rs_allocation</code> variable named <code>lookup</code>, use the Java + method <code>set_lookup(Allocation)</code>. The <code>set</code> methods + are <a href="#asynchronous-model">asynchronous</a>.</li> + +<li><strong>Launch the appropriate kernels and invokable functions.</strong> +<p>Methods to launch a given kernel are +reflected in the same <code>ScriptC_<i>filename</i></code> class with methods named +<code>forEach_<i>mappingKernelName</i>()</code> +or <code>reduce_<i>reductionKernelName</i>()</code>. +These launches are <a href="#asynchronous-model">asynchronous</a>. +Depending on the arguments to the kernel, the +method takes one or more Allocations, all of which must have the same dimensions. By default, a +kernel executes over every coordinate in those dimensions; to execute a kernel over a subset of those coordinates, +pass an appropriate {@link +android.renderscript.Script.LaunchOptions} as the last argument to the <code>forEach</code> or <code>reduce</code> method.</p> + +<p>Launch invokable functions using the <code>invoke_<i>functionName</i></code> methods +reflected in the same <code>ScriptC_<i>filename</i></code> class. +These launches are <a href="#asynchronous-model">asynchronous</a>.</p></li> + +<li><strong>Retrieve data from {@link android.renderscript.Allocation} objects +and <i><a href="#javaFutureType">javaFutureType</a></i> objects.</strong> +In order to +access data from an {@link android.renderscript.Allocation} from Java code, you must copy that data +back to Java using one of the "copy" methods in {@link +android.renderscript.Allocation}. +In order to obtain the result of a reduction kernel, you must use the <code><i>javaFutureType</i>.get()</code> method. +The "copy" and <code>get()</code> methods are <a href="#asynchronous-model">synchronous</a>.</li> + +<li><strong>Tear down the RenderScript context.</strong> You can destroy the RenderScript context with {@link android.renderscript.RenderScript#destroy} or by allowing the RenderScript context -object to be garbage collected. This will cause any further use of any object belonging to that +object to be garbage collected. This causes any further use of any object belonging to that context to throw an exception.</li> </ol> + +<h3 id="asynchronous-model">Asynchronous execution model</h3> + +<p>The reflected <code>forEach</code>, <code>invoke</code>, <code>reduce</code>, + and <code>set</code> methods are asynchronous -- each may return to Java before completing the + requested action. However, the individual actions are serialized in the order in which they are launched.</p> + +<p>The {@link android.renderscript.Allocation} class provides "copy" methods to copy data to + and from Allocations. A "copy" method is synchronous, and is serialized with respect to any + of the asynchronous actions above that touch the same Allocation.</p> + +<p>The reflected <i><a href="#javaFutureType">javaFutureType</a></i> classes provide + a <code>get()</code> method to obtain the result of a reduction. <code>get()</code> is + synchronous, and is serialized with respect to the reduction (which is asynchronous).</p> + +<h2 id="reduction-in-depth">Reduction Kernels in Depth</h2> + +<p><i>Reduction</i> is the process of combining a collection of data into a single +value. This is a useful primitive in parallel programming, with applications such as the +following:</p> +<ul> + <li>computing the sum or product over all the data</li> + <li>computing logical operations (<code>and</code>, <code>or</code>, <code>xor</code>) + over all the data</li> + <li>finding the minimum or maximum value within the data</li> + <li>searching for a specific value or for the coordinate of a specific value within the data</li> +</ul> + +<p>In Android 7.0 (API level 24) and later, RenderScript supports <i>reduction kernels</i> to allow +efficient user-written reduction algorithms. You may launch reduction kernels on inputs with +1, 2, or 3 dimensions.<p> + +<p>An example above shows a simple <a href="#example-addint">addint</a> reduction kernel. +Here is a more complicated <a id="example-findMinAndMax">findMinAndMax</a> reduction kernel +that finds the locations of the minimum and maximum <code>long</code> values in a +1-dimensional {@link android.renderscript.Allocation}:</p> + +<pre> +#define LONG_MAX (long)((1UL << 63) - 1) +#define LONG_MIN (long)(1UL << 63) + +#pragma rs reduce(findMinAndMax) \ + initializer(fMMInit) accumulator(fMMAccumulator) \ + combiner(fMMCombiner) outconverter(fMMOutConverter) + +// Either a value and the location where it was found, or <a href="#INITVAL">INITVAL</a>. +typedef struct { + long val; + int idx; // -1 indicates <a href="#INITVAL">INITVAL</a> +} IndexedVal; + +typedef struct { + IndexedVal min, max; +} MinAndMax; + +// In discussion below, this initial value { { LONG_MAX, -1 }, { LONG_MIN, -1 } } +// is called <a id="INITVAL">INITVAL</a>. +static void fMMInit(MinAndMax *accum) { + accum->min.val = LONG_MAX; + accum->min.idx = -1; + accum->max.val = LONG_MIN; + accum->max.idx = -1; +} + +//---------------------------------------------------------------------- +// In describing the behavior of the accumulator and combiner functions, +// it is helpful to describe hypothetical functions +// IndexedVal min(IndexedVal a, IndexedVal b) +// IndexedVal max(IndexedVal a, IndexedVal b) +// MinAndMax minmax(MinAndMax a, MinAndMax b) +// MinAndMax minmax(MinAndMax accum, IndexedVal val) +// +// The effect of +// IndexedVal min(IndexedVal a, IndexedVal b) +// is to return the IndexedVal from among the two arguments +// whose val is lesser, except that when an IndexedVal +// has a negative index, that IndexedVal is never less than +// any other IndexedVal; therefore, if exactly one of the +// two arguments has a negative index, the min is the other +// argument. Like ordinary arithmetic min and max, this function +// is commutative and associative; that is, +// +// min(A, B) == min(B, A) // commutative +// min(A, min(B, C)) == min((A, B), C) // associative +// +// The effect of +// IndexedVal max(IndexedVal a, IndexedVal b) +// is analogous (greater . . . never greater than). +// +// Then there is +// +// MinAndMax minmax(MinAndMax a, MinAndMax b) { +// return MinAndMax(min(a.min, b.min), max(a.max, b.max)); +// } +// +// Like ordinary arithmetic min and max, the above function +// is commutative and associative; that is: +// +// minmax(A, B) == minmax(B, A) // commutative +// minmax(A, minmax(B, C)) == minmax((A, B), C) // associative +// +// Finally define +// +// MinAndMax minmax(MinAndMax accum, IndexedVal val) { +// return minmax(accum, MinAndMax(val, val)); +// } +//---------------------------------------------------------------------- + +// This function can be explained as doing: +// *accum = minmax(*accum, IndexedVal(in, x)) +// +// This function simply computes minimum and maximum values as if +// INITVAL.min were greater than any other minimum value and +// INITVAL.max were less than any other maximum value. Note that if +// *accum is INITVAL, then this function sets +// *accum = IndexedVal(in, x) +// +// After this function is called, both accum->min.idx and accum->max.idx +// will have nonnegative values: +// - x is always nonnegative, so if this function ever sets one of the +// idx fields, it will set it to a nonnegative value +// - if one of the idx fields is negative, then the corresponding +// val field must be LONG_MAX or LONG_MIN, so the function will always +// set both the val and idx fields +static void fMMAccumulator(MinAndMax *accum, long in, int x) { + IndexedVal me; + me.val = in; + me.idx = x; + + if (me.val <= accum->min.val) + accum->min = me; + if (me.val >= accum->max.val) + accum->max = me; +} + +// This function can be explained as doing: +// *accum = minmax(*accum, *val) +// +// This function simply computes minimum and maximum values as if +// INITVAL.min were greater than any other minimum value and +// INITVAL.max were less than any other maximum value. Note that if +// one of the two accumulator data items is INITVAL, then this +// function sets *accum to the other one. +static void fMMCombiner(MinAndMax *accum, + const MinAndMax *val) { + if ((accum->min.idx < 0) || (val->min.val < accum->min.val)) + accum->min = val->min; + if ((accum->max.idx < 0) || (val->max.val > accum->max.val)) + accum->max = val->max; +} + +static void fMMOutConverter(int2 *result, + const MinAndMax *val) { + result->x = val->min.idx; + result->y = val->max.idx; +} +</pre> + +<p class="note"><strong>NOTE:</strong> There are more example reduction + kernels <a href="#more-example">here</a>.</p> + +<p>In order to run a reduction kernel, the RenderScript runtime creates <em>one or more</em> +variables called <a id="accumulator-data-items"><strong><i>accumulator data +items</i></strong></a> to hold the state of the reduction process. The RenderScript runtime +picks the number of accumulator data items in such a way as to maximize performance. The type +of the accumulator data items (<i>accumType</i>) is determined by the kernel's <i>accumulator +function</i> -- the first argument to that function is a pointer to an accumulator data +item. By default, every accumulator data item is initialized to zero (as if +by <code>memset</code>); however, you may write an <i>initializer function</i> to do something +different.</p> + +<p class="note"><strong>Example:</strong> In the <a href="#example-addint">addint</a> +kernel, the accumulator data items (of type <code>int</code>) are used to add up input +values. There is no initializer function, so each accumulator data item is initialized to +zero.</p> + +<p class="note"><strong>Example:</strong> In +the <a href="#example-findMinAndMax">findMinAndMax</a> kernel, the accumulator data items +(of type <code>MinAndMax</code>) are used to keep track of the minimum and maximum values +found so far. There is an initializer function to set these to <code>LONG_MAX</code> and +<code>LONG_MIN</code>, respectively; and to set the locations of these values to -1, indicating that +the values are not actually present in the (empty) portion of the input that has been +processed.</p> + +<p>RenderScript calls your accumulator function once for every coordinate in the +input(s). Typically, your function should update the accumulator data item in some way +according to the input.</p> + +<p class="note"><strong>Example:</strong> In the <a href="#example-addint">addint</a> +kernel, the accumulator function adds the value of an input Element to the accumulator +data item.</p> + +<p class="note"><strong>Example:</strong> In +the <a href="#example-findMinAndMax">findMinAndMax</a> kernel, the accumulator function +checks to see whether the value of an input Element is less than or equal to the minimum +value recorded in the accumulator data item and/or greater than or equal to the maximum +value recorded in the accumulator data item, and updates the accumulator data item +accordingly.</p> + +<p>After the accumulator function has been called once for every coordinate in the input(s), +RenderScript must <strong>combine</strong> the <a href="#accumulator-data-items">accumulator +data items</a> together into a single accumulator data item. You may write a <i>combiner +function</i> to do this. If the accumulator function has a single input and +no <a href="#special-arguments">special arguments</a>, then you do not need to write a combiner +function; RenderScript will use the accumulator function to combine the accumulator data +items. (You may still write a combiner function if this default behavior is not what you +want.)</p> + +<p class="note"><strong>Example:</strong> In the <a href="#example-addint">addint</a> +kernel, there is no combiner function, so the accumulator function will be used. This is +the correct behavior, because if we split a collection of values into two pieces, and we +add up the values in those two pieces separately, adding up those two sums is the same as +adding up the entire collection.</p> + +<p class="note"><strong>Example:</strong> In +the <a href="#example-findMinAndMax">findMinAndMax</a> kernel, the combiner function +checks to see whether the minimum value recorded in the "source" accumulator data +item <code>*val</code> is less then the minimum value recorded in the "destination" +accumulator data item <code>*accum</code>, and updates <code>*accum</code> +accordingly. It does similar work for the maximum value. This updates <code>*accum</code> +to the state it would have had if all of the input values had been accumulated into +<code>*accum</code> rather than some into <code>*accum</code> and some into +<code>*val</code>.</p> + +<p>After all of the accumulator data items have been combined, RenderScript determines +the result of the reduction to return to Java. You may write an <i>outconverter +function</i> to do this. You do not need to write an outconverter function if you want +the final value of the combined accumulator data items to be the result of the reduction.</p> + +<p class="note"><strong>Example:</strong> In the <a href="#example-addint">addint</a> kernel, +there is no outconverter function. The final value of the combined data items is the sum of +all Elements of the input, which is the value we want to return.</p> + +<p class="note"><strong>Example:</strong> In +the <a href="#example-findMinAndMax">findMinAndMax</a> kernel, the outconverter function +initializes an <code>int2</code> result value to hold the locations of the minimum and +maximum values resulting from the combination of all of the accumulator data items.</p> + +<h3 id="writing-reduction-kernel">Writing a reduction kernel</h3> + +<p><code>#pragma rs reduce</code> defines a reduction kernel by +specifying its name and the names and roles of the functions that make +up the kernel. All such functions must be +<code>static</code>. A reduction kernel always requires an <code>accumulator</code> +function; you can omit some or all of the other functions, depending on what you want the +kernel to do.</p> + +<pre>#pragma rs reduce(<i>kernelName</i>) \ + initializer(<i>initializerName</i>) \ + accumulator(<i>accumulatorName</i>) \ + combiner(<i>combinerName</i>) \ + outconverter(<i>outconverterName</i>) +</pre> + +<p>The meaning of the items in the <code>#pragma</code> is as follows:</p> +<ul> + +<li><code>reduce(<i>kernelName</i>)</code> (mandatory): Specifies that a reduction kernel is +being defined. A reflected Java method <code>reduce_<i>kernelName</i></code> will launch the +kernel.</li> + +<li><p><code>initializer(<i>initializerName</i>)</code> (optional): Specifies the name of the +initializer function for this reduction kernel. When you launch the kernel, RenderScript calls +this function once for each <a href="#accumulator-data-items">accumulator data item</a>. The +function must be defined like this:</p> + +<pre>static void <i>initializerName</i>(<i>accumType</i> *accum) { … }</pre> + +<p><code>accum</code> is a pointer to an accumulator data item for this function to +initialize.</p> + +<p>If you do not provide an initializer function, RenderScript initializes every accumulator +data item to zero (as if by <code>memset</code>), behaving as if there were an initializer +function that looks like this:</p> +<pre>static void <i>initializerName</i>(<i>accumType</i> *accum) { + memset(accum, 0, sizeof(*accum)); +}</pre> +</li> + +<li><p><code><a id="accumulator-function">accumulator(<i>accumulatorName</i>)</a></code> +(mandatory): Specifies the name of the accumulator function for this +reduction kernel. When you launch the kernel, RenderScript calls +this function once for every coordinate in the input(s), to update an +accumulator data item in some way according to the input(s). The function +must be defined like this:</p> + +<pre> +static void <i>accumulatorName</i>(<i>accumType</i> *accum, + <i>in1Type</i> in1, <i>…,</i> <i>inNType</i> in<i>N</i> + <i>[, specialArguments]</i>) { … } +</pre> + +<p><code>accum</code> is a pointer to an accumulator data item for this function to +modify. <code>in1</code> through <code>in<i>N</i></code> are one <em>or more</em> arguments that +are automatically filled in based on the inputs passed to the kernel launch, one argument +per input. The accumulator function may optionally take any of the <a +href="#special-arguments">special arguments</a>.</p> + +<p>An example kernel with multiple inputs is <a href="#dot-product"><code>dotProduct</code></a>.</p> +</li> + +<li><code><a id="combiner-function">combiner(<i>combinerName</i>)</a></code> +(optional): Specifies the name of the combiner function for this +reduction kernel. After RenderScript calls the accumulator function +once for every coordinate in the input(s), it calls this function as many +times as necessary to combine all accumulator data items into a single +accumulator data item. The function must be defined like this:</p> + +<pre>static void <i>combinerName</i>(<i>accumType</i> *accum, const <i>accumType</i> *other) { … }</pre> + +<p><code>accum</code> is a pointer to a "destination" accumulator data item for this +function to modify. <code>other</code> is a pointer to a "source" accumulator data item +for this function to "combine" into <code>*accum</code>.</p> + +<p class="note"><strong>NOTE:</strong> It is possible + that <code>*accum</code>, <code>*other</code>, or both have been initialized but have never + been passed to the accumulator function; that is, one or both have never been updated + according to any input data. For example, in + the <a href="#example-findMinAndMax">findMinAndMax</a> kernel, the combiner + function <code>fMMCombiner</code> explicitly checks for <code>idx < 0</code> because that + indicates such an accumulator data item, whose value is <a href="#INITVAL">INITVAL</a>.</p> + +<p>If you do not provide a combiner function, RenderScript uses the accumulator function in its +place, behaving as if there were a combiner function that looks like this:</p> + +<pre>static void <i>combinerName</i>(<i>accumType</i> *accum, const <i>accumType</i> *other) { + <i>accumulatorName</i>(accum, *other); +}</pre> + +<p>A combiner function is mandatory if the kernel has more than one input, if the input data + type is not the same as the accumulator data type, or if the accumulator function takes one + or more <a href="#special-arguments">special arguments</a>.</p> +</li> + +<li><p><code><a id="outconverter-function">outconverter(<i>outconverterName</i>)</a></code> +(optional): Specifies the name of the outconverter function for this +reduction kernel. After RenderScript combines all of the accumulator +data items, it calls this function to determine the result of the +reduction to return to Java. The function must be defined like +this:</p> + +<pre>static void <i>outconverterName</i>(<i>resultType</i> *result, const <i>accumType</i> *accum) { … }</pre> + +<p><code>result</code> is a pointer to a result data item (allocated but not initialized +by the RenderScript runtime) for this function to initialize with the result of the +reduction. <i>resultType</i> is the type of that data item, which need not be the same +as <i>accumType</i>. <code>accum</code> is a pointer to the final accumulator data item +computed by the <a href="#combiner-function">combiner function</a>.</p> + +<p>If you do not provide an outconverter function, RenderScript copies the final accumulator +data item to the result data item, behaving as if there were an outconverter function that +looks like this:</p> + +<pre>static void <i>outconverterName</i>(<i>accumType</i> *result, const <i>accumType</i> *accum) { + *result = *accum; +}</pre> + +<p>If you want a different result type than the accumulator data type, then the outconverter function is mandatory.</p> +</li> + +</ul> + +<p>Note that a kernel has input types, an accumulator data item type, and a result type, + none of which need to be the same. For example, in + the <a href="#example-findMinAndMax">findMinAndMax</a> kernel, the input + type <code>long</code>, accumulator data item type <code>MinAndMax</code>, and result + type <code>int2</code> are all different.</p> + +<h4 id="assume">What can't you assume?</h4> + +<p>You must not rely on the number of accumulator data items created by RenderScript for a + given kernel launch. There is no guarantee that two launches of the same kernel with the + same input(s) will create the same number of accumulator data items.</p> + +<p>You must not rely on the order in which RenderScript calls the initializer, accumulator, and + combiner functions; it may even call some of them in parallel. There is no guarantee that + two launches of the same kernel with the same input will follow the same order. The only + guarantee is that only the initializer function will ever see an uninitialized accumulator + data item. For example:</p> +<ul> +<li>There is no guarantee that all accumulator data items will be initialized before the + accumulator function is called, although it will only be called on an initialized accumulator + data item.</li> +<li>There is no guarantee on the order in which input Elements are passed to the accumulator + function.</li> +<li>There is no guarantee that the accumulator function has been called for all input Elements + before the combiner function is called.</li> +</ul> + +<p>One consequence of this is that the <a href="#example-findMinAndMax">findMinAndMax</a> + kernel is not deterministic: If the input contains more than one occurrence of the same + minimum or maximum value, you have no way of knowing which occurrence the kernel will + find.</p> + +<h4 id="guarantee">What must you guarantee?</h4> + +<p>Because the RenderScript system can choose to execute a kernel <a href="#assume">in many + different ways</a>, you must follow certain rules to ensure that your kernel behaves the + way you want. If you do not follow these rules, you may get incorrect results, + nondeterministic behavior, or runtime errors.</p> + +<p>The rules below often say that two accumulator data items must have "<a id="the-same">the + same value"</a>. What does this mean? That depends on what you want the kernel to do. For + a mathematical reduction such as <a href="#example-addint">addint</a>, it usually makes sense + for "the same" to mean mathematical equality. For a "pick any" search such + as <a href="#example-findMinAndMax">findMinAndMax</a> ("find the location of minimum and + maximum input values") where there might be more than one occurrence of identical input + values, all locations of a given input value must be considered "the same". You could write + a similar kernel to "find the location of <em>leftmost</em> minimum and maximum input values" + where (say) a minimum value at location 100 is preferred over an identical minimum value at location + 200; for this kernel, "the same" would mean identical <em>location</em>, not merely + identical <em>value</em>, and the accumulator and combiner functions would have to be + different than those for <a href="#example-findMinAndMax">findMinAndMax</a>.</p> + +<strong>The initializer function must create an <i>identity value</i>.</strong> That is, + if <code><i>I</i></code> and <code><i>A</i></code> are accumulator data items initialized + by the initializer function, and <code><i>I</i></code> has never been passed to the + accumulator function (but <code><i>A</i></code> may have been), then +<ul> +<li><code><i>combinerName</i>(&<i>A</i>, &<i>I</i>)</code> must + leave <code><i>A</i></code> <a href="#the-same">the same</a></li> +<li><code><i>combinerName</i>(&<i>I</i>, &<i>A</i>)</code> must + leave <code><i>I</i></code> <a href="#the-same">the same</a> as <code><i>A</i></code></li> +</ul> +<p class="note"><strong>Example:</strong> In the <a href="#example-addint">addint</a> + kernel, an accumulator data item is initialized to zero. The combiner function for this + kernel performs addition; zero is the identity value for addition.</p> +<div class="note"> +<p><strong>Example:</strong> In the <a href="#example-findMinAndMax">findMinAndMax</a> + kernel, an accumulator data item is initialized + to <a href="#INITVAL"><code>INITVAL</code></a>. +<ul> +<li><code>fMMCombiner(&<i>A</i>, &<i>I</i>)</code> leaves <code><i>A</i></code> the same, + because <code><i>I</i></code> is <code>INITVAL</code>.</li> +<li><code>fMMCombiner(&<i>I</i>, &<i>A</i>)</code> sets <code><i>I</i></code> + to <code><i>A</i></code>, because <code><i>I</i></code> is <code>INITVAL</code>.</li> +</ul> +Therefore, <code>INITVAL</code> is indeed an identity value. +</p></div> + +<p><strong>The combiner function must be <i>commutative</i>.</strong> That is, + if <code><i>A</i></code> and <code><i>B</i></code> are accumulator data items initialized + by the initializer function, and that may have been passed to the accumulator function zero + or more times, then <code><i>combinerName</i>(&<i>A</i>, &<i>B</i>)</code> must + set <code><i>A</i></code> to <a href="#the-same">the same value</a> + that <code><i>combinerName</i>(&<i>B</i>, &<i>A</i>)</code> + sets <code><i>B</i></code>.</p> +<p class="note"><strong>Example:</strong> In the <a href="#example-addint">addint</a> + kernel, the combiner function adds the two accumulator data item values; addition is + commutative.</p> +<div class="note"> +<p><strong>Example:</strong> In the <a href="#example-findMinAndMax">findMinAndMax</a> kernel, +<pre> +fMMCombiner(&<i>A</i>, &<i>B</i>) +</pre> +is the same as +<pre> +<i>A</i> = minmax(<i>A</i>, <i>B</i>) +</pre> +and <code>minmax</code> is commutative, so <code>fMMCombiner</code> is also. +</p> +</div> + +<p><strong>The combiner function must be <i>associative</i>.</strong> That is, + if <code><i>A</i></code>, <code><i>B</i></code>, and <code><i>C</i></code> are + accumulator data items initialized by the initializer function, and that may have been passed + to the accumulator function zero or more times, then the following two code sequences must + set <code><i>A</i></code> to <a href="#the-same">the same value</a>:</p> +<ul> +<li><pre> +<i>combinerName</i>(&<i>A</i>, &<i>B</i>); +<i>combinerName</i>(&<i>A</i>, &<i>C</i>); +</pre></li> +<li><pre> +<i>combinerName</i>(&<i>B</i>, &<i>C</i>); +<i>combinerName</i>(&<i>A</i>, &<i>B</i>); +</pre></li> +</ul> +<div class="note"> +<p><strong>Example:</strong> In the <a href="#example-addint">addint</a> kernel, the + combiner function adds the two accumulator data item values: +<ul> +<li><pre> +<i>A</i> = <i>A</i> + <i>B</i> +<i>A</i> = <i>A</i> + <i>C</i> +// Same as +// <i>A</i> = (<i>A</i> + <i>B</i>) + <i>C</i> +</pre></li> +<li><pre> +<i>B</i> = <i>B</i> + <i>C</i> +<i>A</i> = <i>A</i> + <i>B</i> +// Same as +// <i>A</i> = <i>A</i> + (<i>B</i> + <i>C</i>) +// <i>B</i> = <i>B</i> + <i>C</i> +</li> +</ul> +Addition is associative, and so the combiner function is also. +</p> +</div> +<div class="note"> +<p><strong>Example:</strong> In the <a href="#example-findMinAndMax">findMinAndMax</a> kernel, +<pre> +fMMCombiner(&<i>A</i>, &<i>B</i>) +</pre> +is the same as +<pre> +<i>A</i> = minmax(<i>A</i>, <i>B</i>) +</pre> +So the two sequences are +<ul> +<li><pre> +<i>A</i> = minmax(<i>A</i>, <i>B</i>) +<i>A</i> = minmax(<i>A</i>, <i>C</i>) +// Same as +// <i>A</i> = minmax(minmax(<i>A</i>, <i>B</i>), <i>C</i>) +</pre></li> +<li><pre> +<i>B</i> = minmax(<i>B</i>, <i>C</i>) +<i>A</i> = minmax(<i>A</i>, <i>B</i>) +// Same as +// <i>A</i> = minmax(<i>A</i>, minmax(<i>B</i>, <i>C</i>)) +// <i>B</i> = minmax(<i>B</i>, <i>C</i>) +</pre></li> +<code>minmax</code> is associative, and so <code>fMMCombiner</code> is also. +</p> +</div> + +<p><strong>The accumulator function and combiner function together must obey the <i>basic + folding rule</i>.</strong> That is, if <code><i>A</i></code> + and <code><i>B</i></code> are accumulator data items, <code><i>A</i></code> has been + initialized by the initializer function and may have been passed to the accumulator function + zero or more times, <code><i>B</i></code> has not been initialized, and <i>args</i> is + the list of input arguments and special arguments for a particular call to the accumulator + function, then the following two code sequences must set <code><i>A</i></code> + to <a href="#the-same">the same value</a>:</p> +<ul> +<li><pre> +<i>accumulatorName</i>(&<i>A</i>, <i>args</i>); // statement 1 +</pre></li> +<li><pre> +<i>initializerName</i>(&<i>B</i>); // statement 2 +<i>accumulatorName</i>(&<i>B</i>, <i>args</i>); // statement 3 +<i>combinerName</i>(&<i>A</i>, &<i>B</i>); // statement 4 +</pre></li> +</ul> +<div class="note"> +<p><strong>Example:</strong> In the <a href="#example-addint">addint</a> kernel, for an input value <i>V</i>: +<ul> +<li>Statement 1 is the same as <code>A += <i>V</i></code></li> +<li>Statement 2 is the same as <code>B = 0</code></li> +<li>Statement 3 is the same as <code>B += <i>V</i></code>, which is the same as <code>B = <i>V</i></code></li> +<li>Statement 4 is the same as <code>A += B</code>, which is the same as <code>A += <i>V</i></code></li> +</ul> +Statements 1 and 4 set <code><i>A</i></code> to the same value, and so this kernel obeys the +basic folding rule. +</p> +</div> +<div class="note"> +<p><strong>Example:</strong> In the <a href="#example-findMinAndMax">findMinAndMax</a> kernel, for an input + value <i>V</i> at coordinate <i>X</i>: +<ul> +<li>Statement 1 is the same as <code>A = minmax(A, IndexedVal(<i>V</i>, <i>X</i>))</code></li> +<li>Statement 2 is the same as <code>B = <a href="#INITVAL">INITVAL</a></code></li> +<li>Statement 3 is the same as +<pre> +B = minmax(B, IndexedVal(<i>V</i>, <i>X</i>)) +</pre> +which, because <i>B</i> is the initial value, is the same as +<pre> +B = IndexedVal(<i>V</i>, <i>X</i>) +</pre> +</li> +<li>Statement 4 is the same as +<pre> +A = minmax(A, B) +</pre> +which is the same as +<pre> +A = minmax(A, IndexedVal(<i>V</i>, <i>X</i>)) +</pre> +</ul> +Statements 1 and 4 set <code><i>A</i></code> to the same value, and so this kernel obeys the +basic folding rule. +</p> +</div> + +<h3 id="calling-reduction-kernel">Calling a reduction kernel from Java code</h3> + +<p>For a reduction kernel named <i>kernelName</i> defined in the +file <code><i>filename</i>.rs</code>, there are three methods reflected in the +class <code>ScriptC_<i>filename</i></code>:</p> + +<pre> +// Method 1 +public <i>javaFutureType</i> reduce_<i>kernelName</i>(Allocation ain1, <i>…,</i> + Allocation ain<i>N</i>); + +// Method 2 +public <i>javaFutureType</i> reduce_<i>kernelName</i>(Allocation ain1, <i>…,</i> + Allocation ain<i>N</i>, + Script.LaunchOptions sc); + +// Method 3 +public <i>javaFutureType</i> reduce_<i>kernelName</i>(<i><a href="#devec">devecSiIn1Type</a></i>[] in1, …, + <i><a href="#devec">devecSiInNType</a></i>[] in<i>N</i>); +</pre> + +<p>Here are some examples of calling the <a href="#example-addint">addint</a> kernel:</p> +<pre> +ScriptC_example script = new ScriptC_example(mRenderScript); + +// 1D array +// and obtain answer immediately +int input1[] = <i>…</i>; +int sum1 = script.reduce_addint(input1).get(); // Method 3 + +// 2D allocation +// and do some additional work before obtaining answer +Type.Builder typeBuilder = + new Type.Builder(RS, Element.I32(RS)); +typeBuilder.setX(<i>…</i>); +typeBuilder.setY(<i>…</i>); +Allocation input2 = createTyped(RS, typeBuilder.create()); +<i>populateSomehow</i>(input2); // fill in input Allocation with data +script.result_int result2 = script.reduce_addint(input2); // Method 1 +<i>doSomeAdditionalWork</i>(); // might run at same time as reduction +int sum2 = result2.get(); +</pre> + +<p><strong>Method 1</strong> has one input {@link android.renderscript.Allocation} argument for + every input argument in the kernel's <a href="#accumulator-function">accumulator + function</a>. The RenderScript runtime checks to ensure that all of the input Allocations + have the same dimensions and that the {@link android.renderscript.Element} type of each of + the input Allocations matches that of the corresponding input argument of the accumulator + function's prototype. If any of these checks fail, RenderScript throws an exception. The + kernel executes over every coordinate in those dimensions.</p> + +<p><strong>Method 2</strong> is the same as Method 1 except that Method 2 takes an additional + argument <code>sc</code> that can be used to limit the kernel execution to a subset of the + coordinates.</p> + +<p><strong><a id="reduce-method-3">Method 3</a></strong> is the same as Method 1 except that + instead of taking Allocation inputs it takes Java array inputs. This is a convenience that + saves you from having to write code to explicitly create an Allocation and copy data to it + from a Java array. <em>However, using Method 3 instead of Method 1 does not increase the + performance of the code</em>. For each input array, Method 3 creates a temporary + 1-dimensional Allocation with the appropriate {@link android.renderscript.Element} type and + {@link android.renderscript.Allocation#setAutoPadding} enabled, and copies the array to the + Allocation as if by the appropriate <code>copyFrom()</code> method of {@link + android.renderscript.Allocation}. It then calls Method 1, passing those temporary + Allocations.</p> +<p class="note"><strong>NOTE:</strong> If your application will make multiple kernel calls with + the same array, or with different arrays of the same dimensions and Element type, you may improve + performance by explicitly creating, populating, and reusing Allocations yourself, instead of + by using Method 3.</p> +<p><strong><i><a id="javaFutureType">javaFutureType</a></i></strong>, + the return type of the reflected reduction methods, is a reflected + static nested class within the <code>ScriptC_<i>filename</i></code> + class. It represents the future result of a reduction + kernel run. To obtain the actual result of the run, call + the <code>get()</code> method of that class, which returns a value + of type <i>javaResultType</i>. <code>get()</code> is <a href="#asynchronous-model">synchronous</a>.</p> + +<pre> +public class ScriptC_<i>filename</i> extends ScriptC { + public static class <i>javaFutureType</i> { + public <i>javaResultType</i> get() { … } + } +} +</pre> + +<p><strong><i>javaResultType</i></strong> is determined from the <i>resultType</i> of the + <a href="#outconverter-function">outconverter function</a>. Unless <i>resultType</i> is an + unsigned type (scalar, vector, or array), <i>javaResultType</i> is the directly corresponding + Java type. If <i>resultType</i> is an unsigned type and there is a larger Java signed type, + then <i>javaResultType</i> is that larger Java signed type; otherwise, it is the directly + corresponding Java type. For example:</p> +<ul> +<li>If <i>resultType</i> is <code>int</code>, <code>int2</code>, or <code>int[15]</code>, + then <i>javaResultType</i> is <code>int</code>, <code>Int2</code>, + or <code>int[]</code>. All values of <i>resultType</i> can be represented + by <i>javaResultType</i>.</li> +<li>If <i>resultType</i> is <code>uint</code>, <code>uint2</code>, or <code>uint[15]</code>, + then <i>javaResultType</i> is <code>long</code>, <code>Long2</code>, + or <code>long[]</code>. All values of <i>resultType</i> can be represented + by <i>javaResultType</i>.</li> +<li>If <i>resultType</i> is <code>ulong</code>, <code>ulong2</code>, + or <code>ulong[15]</code>, then <i>javaResultType</i> + is <code>long</code>, <code>Long2</code>, or <code>long[]</code>. There are certain values + of <i>resultType</i> that cannot be represented by <i>javaResultType</i>.</li> +</ul> + +<p><strong><i>javaFutureType</i></strong> is the future result type corresponding + to the <i>resultType</i> of the <a href="#outconverter-function">outconverter + function</a>.</p> +<ul> +<li>If <i>resultType</i> is not an array type, then <i>javaFutureType</i> + is <code>result_<i>resultType</i></code>.</li> +<li>If <i>resultType</i> is an array of length <i>Count</i> with members of type <i>memberType</i>, + then <i>javaFutureType</i> is <code>resultArray<i>Count</i>_<i>memberType</i></code>.</li> +</ul> + +<p>For example:</p> + +<pre> +public class ScriptC_<i>filename</i> extends ScriptC { + // for kernels with int result + public static class result_int { + public int get() { … } + } + + // for kernels with int[10] result + public static class resultArray10_int { + public int[] get() { … } + } + + // for kernels with int2 result + // note that the Java type name "Int2" is not the same as the script type name "int2" + public static class result_int2 { + public Int2 get() { … } + } + + // for kernels with int2[10] result + // note that the Java type name "Int2" is not the same as the script type name "int2" + public static class resultArray10_int2 { + public Int2[] get() { … } + } + + // for kernels with uint result + // note that the Java type "long" is a wider signed type than the unsigned script type "uint" + public static class result_uint { + public long get() { … } + } + + // for kernels with uint[10] result + // note that the Java type "long" is a wider signed type than the unsigned script type "uint" + public static class resultArray10_uint { + public long[] get() { … } + } + + // for kernels with uint2 result + // note that the Java type "Long2" is a wider signed type than the unsigned script type "uint2" + public static class result_uint2 { + public Long2 get() { … } + } + + // for kernels with uint2[10] result + // note that the Java type "Long2" is a wider signed type than the unsigned script type "uint2" + public static class resultArray10_uint2 { + public Long2[] get() { … } + } +} +</pre> + +<p>If <i>javaResultType</i> is an object type (including an array type), each call + to <code><i>javaFutureType</i>.get()</code> on the same instance will return the same + object.</p> + +<p>If <i>javaResultType</i> cannot represent all values of type <i>resultType</i>, and a + reduction kernel produces an unrepresentible value, + then <code><i>javaFutureType</i>.get()</code> throws an exception.</p> + +<h4 id="devec">Method 3 and <i>devecSiInXType</i></h4> + +<p><strong><i>devecSiInXType</i></strong> is the Java type corresponding to + the <i>inXType</i> of the corresponding argument of + the <a href="#accumulator-function">accumulator function</a>. Unless <i>inXType</i> is an + unsigned type or a vector type, <i>devecSiInXType</i> is the directly corresponding Java + type. If <i>inXType</i> is an unsigned scalar type, then <i>devecSiInXType</i> is the + Java type directly corresponding to the signed scalar type of the same + size. If <i>inXType</i> is a signed vector type, then <i>devecSiInXType</i> is the Java + type directly corresponding to the vector component type. If <i>inXType</i> is an unsigned + vector type, then <i>devecSiInXType</i> is the Java type directly corresponding to the + signed scalar type of the same size as the vector component type. For example:</p> +<ul> +<li>If <i>inXType</i> is <code>int</code>, then <i>devecSiInXType</i> + is <code>int</code>.</li> +<li>If <i>inXType</i> is <code>int2</code>, then <i>devecSiInXType</i> + is <code>int</code>. The array is a <em>flattened</em> representation: It has twice as + many <em>scalar</em> Elements as the Allocation has 2-component <em>vector</em> + Elements. This is the same way that the <code>copyFrom()</code> methods of {@link + android.renderscript.Allocation} work.</li> +<li>If <i>inXType</i> is <code>uint</code>, then <i>deviceSiInXType</i> + is <code>int</code>. A signed value in the Java array is interpreted as an unsigned value of + the same bitpattern in the Allocation. This is the same way that the <code>copyFrom()</code> + methods of {@link android.renderscript.Allocation} work.</li> +<li>If <i>inXType</i> is <code>uint2</code>, then <i>deviceSiInXType</i> + is <code>int</code>. This is a combination of the way <code>int2</code> and <code>uint</code> + are handled: The array is a flattened representation, and Java array signed values are + interpreted as RenderScript unsigned Element values.</li> +</ul> + +<p>Note that for <a href="#reduce-method-3">Method 3</a>, input types are handled differently +than result types:</p> + +<ul> +<li>A script's vector input is flattened on the Java side, whereas a script's vector result is not.</li> +<li>A script's unsigned input is represented as a signed input of the same size on the Java + side, whereas a script's unsigned result is represented as a widened signed type on the Java + side (except in the case of <code>ulong</code>).</li> +</ul> + +<h3 id="more-example">More example reduction kernels</h3> + +<pre id="dot-product"> +#pragma rs reduce(dotProduct) \ + accumulator(dotProductAccum) combiner(dotProductSum) + +// Note: No initializer function -- therefore, +// each accumulator data item is implicitly initialized to 0.0f. + +static void dotProductAccum(float *accum, float in1, float in2) { + *accum += in1*in2; +} + +// combiner function +static void dotProductSum(float *accum, const float *val) { + *accum += *val; +} +</pre> + +<pre> +// Find a zero Element in a 2D allocation; return (-1, -1) if none +#pragma rs reduce(fz2) \ + initializer(fz2Init) \ + accumulator(fz2Accum) combiner(fz2Combine) + +static void fz2Init(int2 *accum) { accum->x = accum->y = -1; } + +static void fz2Accum(int2 *accum, + int inVal, + int x /* special arg */, + int y /* special arg */) { + if (inVal==0) { + accum->x = x; + accum->y = y; + } +} + +static void fz2Combine(int2 *accum, const int2 *accum2) { + if (accum2->x >= 0) *accum = *accum2; +} +</pre> + +<pre> +// Note that this kernel returns an array to Java +#pragma rs reduce(histogram) \ + accumulator(hsgAccum) combiner(hsgCombine) + +#define BUCKETS 256 +typedef uint32_t Histogram[BUCKETS]; + +// Note: No initializer function -- +// therefore, each bucket is implicitly initialized to 0. + +static void hsgAccum(Histogram *h, uchar in) { ++(*h)[in]; } + +static void hsgCombine(Histogram *accum, + const Histogram *addend) { + for (int i = 0; i < BUCKETS; ++i) + (*accum)[i] += (*addend)[i]; +} + +// Determines the mode (most frequently occurring value), and returns +// the value and the frequency. +// +// If multiple values have the same highest frequency, returns the lowest +// of those values. +// +// Shares functions with the histogram reduction kernel. +#pragma rs reduce(mode) \ + accumulator(hsgAccum) combiner(hsgCombine) \ + outconverter(modeOutConvert) + +static void modeOutConvert(int2 *result, const Histogram *h) { + uint32_t mode = 0; + for (int i = 1; i < BUCKETS; ++i) + if ((*h)[i] > (*h)[mode]) mode = i; + result->x = mode; + result->y = (*h)[mode]; +} +</pre> diff --git a/docs/html/training/testing/unit-testing/local-unit-tests.jd b/docs/html/training/testing/unit-testing/local-unit-tests.jd index 8b109ee36a0e..d19de4f6544a 100644 --- a/docs/html/training/testing/unit-testing/local-unit-tests.jd +++ b/docs/html/training/testing/unit-testing/local-unit-tests.jd @@ -112,12 +112,16 @@ Hamcrest matchers</a> (such as the {@code is()} and {@code equalTo()} methods) t returned result against the expected result.</p> <h3 id="mocking-dependencies">Mock Android dependencies</h3> -<p> -By default, the <a href="{@docRoot}tools/building/plugin-for-gradle.html"> -Android Plug-in for Gradle</a> executes your local unit tests against a modified -version of the {@code android.jar} library, which does not contain any actual code. Instead, method -calls to Android classes from your unit test throw an exception. -</p> + +<p>By default, the <a href= +"{@docRoot}tools/building/plugin-for-gradle.html">Android Plug-in for +Gradle</a> executes your local unit tests against a modified version of the +{@code android.jar} library, which does not contain any actual code. Instead, +method calls to Android classes from your unit test throw an exception. This is +to make sure you test only your code and do not depend on any +particular behavior of the Android platform (that you have not explicitly +mocked).</p> + <p> You can use a mocking framework to stub out external dependencies in your code, to easily test that your component interacts with a dependency in an expected way. By substituting Android dependencies @@ -195,6 +199,26 @@ class="external-link">Mockito API reference</a> and the class="external-link">sample code</a>. </p> +<p>If the exceptions thrown by Android APIs in the +<code>android.jar</code> are problematic for your tests, you can change the behavior so that methods +instead return either null or zero by adding the following configuration in your project's +top-level <code>build.gradle</code> file:</p> + +<pre> +android { + ... + testOptions { + unitTests.returnDefaultValues = true + } +} +</pre> + +<p class="caution"><strong>Caution:</strong> +Setting the <code>returnDefaultValues</code> property to <code>true</code> +should be done with care. The null/zero return values can introduce +regressions in your tests, which are hard to debug and might allow failing tests +to pass. Only use it as a last resort.</p> + <h2 id="run">Run Local Unit Tests</h2> diff --git a/libs/common_time/common_time_server.cpp b/libs/common_time/common_time_server.cpp index f72ffaa63712..b1495effbc81 100644 --- a/libs/common_time/common_time_server.cpp +++ b/libs/common_time/common_time_server.cpp @@ -615,12 +615,11 @@ bool CommonTimeServer::handlePacket() { ssize_t recvBytes = recvfrom( mSocket, buf, sizeof(buf), 0, - reinterpret_cast<const sockaddr *>(&srcAddr), &srcAddrLen); + reinterpret_cast<sockaddr *>(&srcAddr), &srcAddrLen); if (recvBytes < 0) { - mBadPktLog.log(ANDROID_LOG_ERROR, LOG_TAG, - "recvfrom failed (res %d, errno %d)", - recvBytes, errno); + mBadPktLog.log(ANDROID_LOG_ERROR, LOG_TAG, "recvfrom failed (%s)", + strerror(errno)); return false; } diff --git a/libs/hwui/Animator.h b/libs/hwui/Animator.h index 72bac6c2a515..aac355c11ac9 100644 --- a/libs/hwui/Animator.h +++ b/libs/hwui/Animator.h @@ -124,7 +124,7 @@ protected: Finished, }; - BaseRenderNodeAnimator(float finalValue); + explicit BaseRenderNodeAnimator(float finalValue); virtual ~BaseRenderNodeAnimator(); virtual float getValue(RenderNode* target) const = 0; diff --git a/libs/hwui/AssetAtlas.cpp b/libs/hwui/AssetAtlas.cpp index 6afff1b7158e..e2e7037202b8 100644 --- a/libs/hwui/AssetAtlas.cpp +++ b/libs/hwui/AssetAtlas.cpp @@ -27,7 +27,7 @@ namespace uirenderer { // Lifecycle /////////////////////////////////////////////////////////////////////////////// -void AssetAtlas::init(sp<GraphicBuffer> buffer, int64_t* map, int count) { +void AssetAtlas::init(const sp<GraphicBuffer>& buffer, int64_t* map, int count) { if (mImage) { return; } diff --git a/libs/hwui/AssetAtlas.h b/libs/hwui/AssetAtlas.h index 75400ff494c3..b32e51851b94 100644 --- a/libs/hwui/AssetAtlas.h +++ b/libs/hwui/AssetAtlas.h @@ -109,7 +109,7 @@ public: * initialized. To re-initialize the atlas, you must * first call terminate(). */ - ANDROID_API void init(sp<GraphicBuffer> buffer, int64_t* map, int count); + ANDROID_API void init(const sp<GraphicBuffer>& buffer, int64_t* map, int count); /** * Destroys the atlas texture. This object can be diff --git a/libs/hwui/DisplayList.h b/libs/hwui/DisplayList.h index a8205c854c14..c5d87676b7ff 100644 --- a/libs/hwui/DisplayList.h +++ b/libs/hwui/DisplayList.h @@ -101,7 +101,7 @@ public: const LsaVector<const SkBitmap*>& getBitmapResources() const { return bitmapResources; } const LsaVector<FunctorContainer>& getFunctors() const { return functors; } - const LsaVector<VectorDrawableRoot*>& getVectorDrawables() { return vectorDrawables; } + const LsaVector<VectorDrawableRoot*>& getVectorDrawables() const { return vectorDrawables; } size_t addChild(NodeOpType* childOp); diff --git a/libs/hwui/Image.h b/libs/hwui/Image.h index 25145354a4f0..b8f5a5bec087 100644 --- a/libs/hwui/Image.h +++ b/libs/hwui/Image.h @@ -38,7 +38,7 @@ public: * cannot be created, getTexture() will return 0 and getImage() will * return EGL_NO_IMAGE_KHR. */ - Image(sp<GraphicBuffer> buffer); + explicit Image(sp<GraphicBuffer> buffer); ~Image(); /** diff --git a/libs/hwui/Interpolator.h b/libs/hwui/Interpolator.h index 66ce1197f060..65120087ff60 100644 --- a/libs/hwui/Interpolator.h +++ b/libs/hwui/Interpolator.h @@ -43,7 +43,7 @@ public: class ANDROID_API AccelerateInterpolator : public Interpolator { public: - AccelerateInterpolator(float factor) : mFactor(factor), mDoubleFactor(factor*2) {} + explicit AccelerateInterpolator(float factor) : mFactor(factor), mDoubleFactor(factor*2) {} virtual float interpolate(float input) override; private: const float mFactor; @@ -52,7 +52,7 @@ private: class ANDROID_API AnticipateInterpolator : public Interpolator { public: - AnticipateInterpolator(float tension) : mTension(tension) {} + explicit AnticipateInterpolator(float tension) : mTension(tension) {} virtual float interpolate(float input) override; private: const float mTension; @@ -60,7 +60,7 @@ private: class ANDROID_API AnticipateOvershootInterpolator : public Interpolator { public: - AnticipateOvershootInterpolator(float tension) : mTension(tension) {} + explicit AnticipateOvershootInterpolator(float tension) : mTension(tension) {} virtual float interpolate(float input) override; private: const float mTension; @@ -73,7 +73,7 @@ public: class ANDROID_API CycleInterpolator : public Interpolator { public: - CycleInterpolator(float cycles) : mCycles(cycles) {} + explicit CycleInterpolator(float cycles) : mCycles(cycles) {} virtual float interpolate(float input) override; private: const float mCycles; @@ -81,7 +81,7 @@ private: class ANDROID_API DecelerateInterpolator : public Interpolator { public: - DecelerateInterpolator(float factor) : mFactor(factor) {} + explicit DecelerateInterpolator(float factor) : mFactor(factor) {} virtual float interpolate(float input) override; private: const float mFactor; @@ -94,7 +94,7 @@ public: class ANDROID_API OvershootInterpolator : public Interpolator { public: - OvershootInterpolator(float tension) : mTension(tension) {} + explicit OvershootInterpolator(float tension) : mTension(tension) {} virtual float interpolate(float input) override; private: const float mTension; diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp index c90abad10ccf..dd20a76eb561 100644 --- a/libs/hwui/RenderNode.cpp +++ b/libs/hwui/RenderNode.cpp @@ -23,6 +23,7 @@ #include "RecordedOp.h" #include "TreeInfo.h" #include "utils/MathUtils.h" +#include "utils/StringUtils.h" #include "utils/TraceUtils.h" #include "VectorDrawable.h" #include "renderstate/RenderState.h" @@ -68,31 +69,36 @@ void RenderNode::setStagingDisplayList(DisplayList* displayList, TreeObserver* o * This function is a simplified version of replay(), where we simply retrieve and log the * display list. This function should remain in sync with the replay() function. */ -void RenderNode::output(uint32_t level, const char* label) { - ALOGD("%s (%s %p%s%s%s%s%s)", - label, - getName(), - this, - (MathUtils::isZero(properties().getAlpha()) ? ", zero alpha" : ""), - (properties().hasShadow() ? ", casting shadow" : ""), - (isRenderable() ? "" : ", empty"), - (properties().getProjectBackwards() ? ", projected" : ""), - (mLayer != nullptr ? ", on HW Layer" : "")); - properties().debugOutputProperties(level + 1); +void RenderNode::output() { + LogcatStream strout; + strout << "Root"; + output(strout, 0); +} + +void RenderNode::output(std::ostream& output, uint32_t level) { + output << " (" << getName() << " " << this + << (MathUtils::isZero(properties().getAlpha()) ? ", zero alpha" : "") + << (properties().hasShadow() ? ", casting shadow" : "") + << (isRenderable() ? "" : ", empty") + << (properties().getProjectBackwards() ? ", projected" : "") + << (mLayer != nullptr ? ", on HW Layer" : "") + << ")" << std::endl; + + properties().debugOutputProperties(output, level + 1); if (mDisplayList) { for (auto&& op : mDisplayList->getOps()) { - std::stringstream strout; - OpDumper::dump(*op, strout, level + 1); + OpDumper::dump(*op, output, level + 1); if (op->opId == RecordedOpId::RenderNodeOp) { auto rnOp = reinterpret_cast<const RenderNodeOp*>(op); - rnOp->renderNode->output(level + 1, strout.str().c_str()); + rnOp->renderNode->output(output, level + 1); } else { - ALOGD("%s", strout.str().c_str()); + output << std::endl; } } } - ALOGD("%*s/RenderNode(%s %p)", level * 2, "", getName(), this); + output << std::string(level * 2, ' ') << "/RenderNode(" << getName() << " " << this << ")"; + output << std::endl; } void RenderNode::copyTo(proto::RenderNode *pnode) { diff --git a/libs/hwui/RenderNode.h b/libs/hwui/RenderNode.h index ee045aaae0a4..a0679b1e55f0 100644 --- a/libs/hwui/RenderNode.h +++ b/libs/hwui/RenderNode.h @@ -102,7 +102,7 @@ public: void computeOrdering(); - ANDROID_API void output(uint32_t level = 0, const char* label = "Root"); + ANDROID_API void output(); ANDROID_API int getDebugSize(); void copyTo(proto::RenderNode* node); @@ -247,6 +247,7 @@ private: void incParentRefCount() { mParentCount++; } void decParentRefCount(TreeObserver* observer, TreeInfo* info = nullptr); + void output(std::ostream& output, uint32_t level); String8 mName; sp<VirtualLightRefBase> mUserContext; diff --git a/libs/hwui/RenderProperties.cpp b/libs/hwui/RenderProperties.cpp index 7e3cad4ca9d0..b0114bce4b51 100644 --- a/libs/hwui/RenderProperties.cpp +++ b/libs/hwui/RenderProperties.cpp @@ -99,26 +99,34 @@ RenderProperties& RenderProperties::operator=(const RenderProperties& other) { return *this; } -void RenderProperties::debugOutputProperties(const int level) const { - if (mPrimitiveFields.mLeft != 0 || mPrimitiveFields.mTop != 0) { - ALOGD("%*s(Translate (left, top) %d, %d)", level * 2, "", - mPrimitiveFields.mLeft, mPrimitiveFields.mTop); - } - if (mStaticMatrix) { - ALOGD("%*s(ConcatMatrix (static) %p: " SK_MATRIX_STRING ")", - level * 2, "", mStaticMatrix, SK_MATRIX_ARGS(mStaticMatrix)); +static void dumpMatrix(std::ostream& output, std::string& indent, + const char* label, SkMatrix* matrix) { + if (matrix) { + output << indent << "(" << label << " " << matrix << ": "; + output << std::fixed << std::setprecision(2); + output << "[" << matrix->get(0) << " "<< matrix->get(1) << " " << matrix->get(2) << "]"; + output << " [" << matrix->get(3) << " "<< matrix->get(4) << " " << matrix->get(5) << "]"; + output << " [" << matrix->get(6) << " "<< matrix->get(7) << " " << matrix->get(8) << "]"; + output << ")" << std::endl; } - if (mAnimationMatrix) { - ALOGD("%*s(ConcatMatrix (animation) %p: " SK_MATRIX_STRING ")", - level * 2, "", mAnimationMatrix, SK_MATRIX_ARGS(mAnimationMatrix)); +} + +void RenderProperties::debugOutputProperties(std::ostream& output, const int level) const { + auto indent = std::string(level * 2, ' '); + if (mPrimitiveFields.mLeft != 0 || mPrimitiveFields.mTop != 0) { + output << indent << "(Translate (left, top) " << mPrimitiveFields.mLeft + << ", " << mPrimitiveFields.mTop << ")" << std::endl; } + dumpMatrix(output, indent, "ConcatMatrix (static)", mStaticMatrix); + dumpMatrix(output, indent, "ConcatMatrix (animation)", mAnimationMatrix); + + output << std::fixed << std::setprecision(2); if (hasTransformMatrix()) { if (isTransformTranslateOnly()) { - ALOGD("%*s(Translate %.2f, %.2f, %.2f)", - level * 2, "", getTranslationX(), getTranslationY(), getZ()); + output << indent << "(Translate " << getTranslationX() << ", " << getTranslationY() + << ", " << getZ() << ")" << std::endl; } else { - ALOGD("%*s(ConcatMatrix %p: " SK_MATRIX_STRING ")", - level * 2, "", mComputedFields.mTransformMatrix, SK_MATRIX_ARGS(mComputedFields.mTransformMatrix)); + dumpMatrix(output, indent, "ConcatMatrix ", mComputedFields.mTransformMatrix); } } @@ -132,7 +140,7 @@ void RenderProperties::debugOutputProperties(const int level) const { if (CC_LIKELY(isLayer || !getHasOverlappingRendering())) { // simply scale rendering content's alpha - ALOGD("%*s(ScaleAlpha %.2f)", level * 2, "", mPrimitiveFields.mAlpha); + output << indent << "(ScaleAlpha " << mPrimitiveFields.mAlpha << ")" << std::endl; } else { // savelayeralpha to create an offscreen buffer to apply alpha Rect layerBounds(0, 0, getWidth(), getHeight()); @@ -140,35 +148,40 @@ void RenderProperties::debugOutputProperties(const int level) const { getClippingRectForFlags(clipFlags, &layerBounds); clipFlags = 0; // all clipping done by savelayer } - ALOGD("%*s(SaveLayerAlpha %d, %d, %d, %d, %d, 0x%x)", level * 2, "", - (int)layerBounds.left, (int)layerBounds.top, - (int)layerBounds.right, (int)layerBounds.bottom, - (int)(mPrimitiveFields.mAlpha * 255), - SaveFlags::HasAlphaLayer | SaveFlags::ClipToLayer); + output << indent << "(SaveLayerAlpha " + << (int)layerBounds.left << ", " << (int)layerBounds.top << ", " + << (int)layerBounds.right << ", " << (int)layerBounds.bottom << ", " + << (int)(mPrimitiveFields.mAlpha * 255) << ", 0x" << std::hex + << (SaveFlags::HasAlphaLayer | SaveFlags::ClipToLayer) << ")" << std::dec + << std::endl; } } if (clipFlags) { Rect clipRect; getClippingRectForFlags(clipFlags, &clipRect); - ALOGD("%*s(ClipRect %d, %d, %d, %d)", level * 2, "", - (int)clipRect.left, (int)clipRect.top, (int)clipRect.right, (int)clipRect.bottom); + output << indent << "(ClipRect " + << (int)clipRect.left << ", " << (int)clipRect.top << ", " + << (int)clipRect.right << ", " << (int)clipRect.bottom << ")" << std::endl; } if (getRevealClip().willClip()) { Rect bounds; getRevealClip().getBounds(&bounds); - ALOGD("%*s(Clip to reveal clip with bounds %.2f %.2f %.2f %.2f)", level * 2, "", - RECT_ARGS(bounds)); + output << indent << "(Clip to reveal clip with bounds " + << bounds.left << ", " << bounds.top << ", " + << bounds.right << ", " << bounds.bottom << ")" << std::endl; } auto& outline = mPrimitiveFields.mOutline; if (outline.getShouldClip()) { if (outline.isEmpty()) { - ALOGD("%*s(Clip to empty outline)", level * 2, ""); + output << indent << "(Clip to empty outline)"; } else if (outline.willClip()) { - ALOGD("%*s(Clip to outline with bounds %.2f %.2f %.2f %.2f)", level * 2, "", - RECT_ARGS(outline.getBounds())); + const Rect& bounds = outline.getBounds(); + output << indent << "(Clip to outline with bounds " + << bounds.left << ", " << bounds.top << ", " + << bounds.right << ", " << bounds.bottom << ")" << std::endl; } } } diff --git a/libs/hwui/RenderProperties.h b/libs/hwui/RenderProperties.h index 00494a12b808..2f5223cedb86 100644 --- a/libs/hwui/RenderProperties.h +++ b/libs/hwui/RenderProperties.h @@ -35,6 +35,7 @@ #include <cutils/compiler.h> #include <androidfw/ResourceTypes.h> #include <utils/Log.h> +#include <ostream> class SkBitmap; class SkColorFilter; @@ -574,7 +575,7 @@ public: return mPrimitiveFields.mProjectBackwards; } - void debugOutputProperties(const int level) const; + void debugOutputProperties(std::ostream& output, const int level) const; void updateMatrix(); diff --git a/libs/hwui/renderstate/RenderState.h b/libs/hwui/renderstate/RenderState.h index 731d9bbb3355..9e0fb121be65 100644 --- a/libs/hwui/renderstate/RenderState.h +++ b/libs/hwui/renderstate/RenderState.h @@ -106,7 +106,7 @@ private: void interruptForFunctorInvoke(); void resumeFromFunctorInvoke(); - RenderState(renderthread::RenderThread& thread); + explicit RenderState(renderthread::RenderThread& thread); ~RenderState(); diff --git a/libs/hwui/renderthread/EglManager.h b/libs/hwui/renderthread/EglManager.h index 459baed70e40..41047fecf960 100644 --- a/libs/hwui/renderthread/EglManager.h +++ b/libs/hwui/renderthread/EglManager.h @@ -86,7 +86,7 @@ public: private: friend class RenderThread; - EglManager(RenderThread& thread); + explicit EglManager(RenderThread& thread); // EglContext is never destroyed, method is purposely not implemented ~EglManager(); diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp index d6eea877de0c..3edd42372653 100644 --- a/libs/hwui/renderthread/RenderProxy.cpp +++ b/libs/hwui/renderthread/RenderProxy.cpp @@ -157,7 +157,7 @@ void RenderProxy::updateSurface(const sp<Surface>& surface) { SETUP_TASK(updateSurface); args->context = mContext; args->surface = surface.get(); - postAndWait(task); + post(task); } CREATE_BRIDGE2(pauseSurface, CanvasContext* context, Surface* surface) { diff --git a/libs/hwui/tests/unit/RenderNodeTests.cpp b/libs/hwui/tests/unit/RenderNodeTests.cpp index fd3cf3731f04..0d90afa06ab4 100644 --- a/libs/hwui/tests/unit/RenderNodeTests.cpp +++ b/libs/hwui/tests/unit/RenderNodeTests.cpp @@ -15,6 +15,7 @@ */ #include <gtest/gtest.h> +#include <VectorDrawable.h> #include "AnimationContext.h" #include "DamageAccumulator.h" @@ -132,3 +133,38 @@ RENDERTHREAD_TEST(RenderNode, prepareTree_nullableDisplayList) { canvasContext->destroy(nullptr); } + +RENDERTHREAD_TEST(RenderNode, prepareTree_HwLayer_AVD_enqueueDamage) { + + VectorDrawable::Group* group = new VectorDrawable::Group(); + VectorDrawableRoot* vectorDrawable = new VectorDrawableRoot(group); + auto rootNode = TestUtils::createNode(0, 0, 200, 400, + [&](RenderProperties& props, Canvas& canvas) { + canvas.drawVectorDrawable(vectorDrawable); + }); + ContextFactory contextFactory; + std::unique_ptr<CanvasContext> canvasContext(CanvasContext::create( + renderThread, false, rootNode.get(), &contextFactory)); + TreeInfo info(TreeInfo::MODE_RT_ONLY, *canvasContext.get()); + DamageAccumulator damageAccumulator; + LayerUpdateQueue layerUpdateQueue; + info.damageAccumulator = &damageAccumulator; + info.layerUpdateQueue = &layerUpdateQueue; + info.observer = nullptr; + + // Put node on HW layer + rootNode->mutateStagingProperties().mutateLayerProperties().setType(LayerType::RenderLayer); + + TestUtils::syncHierarchyPropertiesAndDisplayList(rootNode); + rootNode->prepareTree(info); + + // Check that the VD is in the dislay list, and the layer update queue contains the correct + // damage rect. + EXPECT_FALSE(rootNode->getDisplayList()->getVectorDrawables().empty()); + EXPECT_FALSE(info.layerUpdateQueue->entries().empty()); + EXPECT_EQ(rootNode.get(), info.layerUpdateQueue->entries().at(0).renderNode); + EXPECT_EQ(uirenderer::Rect(0, 0, 200, 400), info.layerUpdateQueue->entries().at(0).damage); + + delete vectorDrawable; + canvasContext->destroy(nullptr); +} diff --git a/libs/hwui/thread/TaskManager.h b/libs/hwui/thread/TaskManager.h index 0e4ffdca496d..c9d12bc6044b 100644 --- a/libs/hwui/thread/TaskManager.h +++ b/libs/hwui/thread/TaskManager.h @@ -78,7 +78,7 @@ private: class WorkerThread: public Thread { public: - explicit WorkerThread(const String8 name): mSignal(Condition::WAKE_UP_ONE), mName(name) { } + explicit WorkerThread(const String8& name): mSignal(Condition::WAKE_UP_ONE), mName(name) { } bool addTask(const TaskWrapper& task); size_t getTaskCount() const; diff --git a/libs/hwui/utils/StringUtils.h b/libs/hwui/utils/StringUtils.h index 5add95711f2d..af5d10f8522b 100644 --- a/libs/hwui/utils/StringUtils.h +++ b/libs/hwui/utils/StringUtils.h @@ -16,10 +16,14 @@ #ifndef STRING_UTILS_H #define STRING_UTILS_H +#include <iomanip> +#include <iostream> +#include <ostream> +#include <sstream> #include <string> #include <unordered_set> -#include <ostream> -#include <iomanip> + +#include <utils/Log.h> namespace android { namespace uirenderer { @@ -51,6 +55,22 @@ struct SizePrinter { } }; +class LogcatStream: public std::ostream { + class LogcatStreamBuf: public std::stringbuf { + virtual int sync() { + ALOGD("%s", str().c_str()); + str(""); + return 0; + } + }; + + LogcatStreamBuf buffer; +public: + LogcatStream() + :std::ostream(&buffer) { + } +}; + } /* namespace uirenderer */ } /* namespace android */ diff --git a/libs/hwui/utils/Timing.h b/libs/hwui/utils/Timing.h index dd8847add2e8..4b1fabe42c35 100644 --- a/libs/hwui/utils/Timing.h +++ b/libs/hwui/utils/Timing.h @@ -22,7 +22,7 @@ #define TIME_METHOD() MethodTimer __method_timer(__func__) class MethodTimer { public: - MethodTimer(const char* name) + explicit MethodTimer(const char* name) : mMethodName(name) { gettimeofday(&mStart, nullptr); } diff --git a/media/java/android/media/ExifInterface.java b/media/java/android/media/ExifInterface.java index 268e44206157..d413083c2ebb 100644 --- a/media/java/android/media/ExifInterface.java +++ b/media/java/android/media/ExifInterface.java @@ -25,6 +25,7 @@ import android.system.Os; import android.system.OsConstants; import android.util.Log; import android.util.Pair; +import android.annotation.IntDef; import java.io.BufferedInputStream; import java.io.ByteArrayInputStream; @@ -55,6 +56,8 @@ import java.util.Set; import java.util.TimeZone; import java.util.regex.Matcher; import java.util.regex.Pattern; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import libcore.io.IoUtils; import libcore.io.Streams; @@ -69,7 +72,6 @@ import libcore.io.Streams; public class ExifInterface { private static final String TAG = "ExifInterface"; private static final boolean DEBUG = false; - private static final boolean HANDLE_RAW = false; // The Exif tag names. See Tiff 6.0 Section 3 and Section 8. /** Type is String. */ @@ -1167,16 +1169,24 @@ public class ExifInterface { // The following values are used for indicating pointers to the other Image File Directories. // Indices of Exif Ifd tag groups - private static final int IFD_TIFF_HINT = 0; - private static final int IFD_EXIF_HINT = 1; - private static final int IFD_GPS_HINT = 2; - private static final int IFD_INTEROPERABILITY_HINT = 3; - private static final int IFD_THUMBNAIL_HINT = 4; - private static final int IFD_PREVIEW_HINT = 5; - private static final int ORF_MAKER_NOTE_HINT = 6; - private static final int ORF_CAMERA_SETTINGS_HINT = 7; - private static final int ORF_IMAGE_PROCESSING_HINT = 8; - private static final int PEF_HINT = 9; + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef({IFD_TYPE_PRIMARY, IFD_TYPE_EXIF, IFD_TYPE_GPS, IFD_TYPE_INTEROPERABILITY, + IFD_TYPE_THUMBNAIL, IFD_TYPE_PREVIEW, IFD_TYPE_ORF_MAKER_NOTE, + IFD_TYPE_ORF_CAMERA_SETTINGS, IFD_TYPE_ORF_IMAGE_PROCESSING, IFD_TYPE_PEF}) + public @interface IfdType {} + + private static final int IFD_TYPE_PRIMARY = 0; + private static final int IFD_TYPE_EXIF = 1; + private static final int IFD_TYPE_GPS = 2; + private static final int IFD_TYPE_INTEROPERABILITY = 3; + private static final int IFD_TYPE_THUMBNAIL = 4; + private static final int IFD_TYPE_PREVIEW = 5; + private static final int IFD_TYPE_ORF_MAKER_NOTE = 6; + private static final int IFD_TYPE_ORF_CAMERA_SETTINGS = 7; + private static final int IFD_TYPE_ORF_IMAGE_PROCESSING = 8; + private static final int IFD_TYPE_PEF = 9; + // List of Exif tag groups private static final ExifTag[][] EXIF_TAGS = new ExifTag[][] { IFD_TIFF_TAGS, IFD_EXIF_TAGS, IFD_GPS_TAGS, IFD_INTEROPERABILITY_TAGS, @@ -1192,11 +1202,7 @@ public class ExifInterface { new ExifTag(TAG_ORF_CAMERA_SETTINGS_IFD_POINTER, 8224, IFD_FORMAT_BYTE), new ExifTag(TAG_ORF_IMAGE_PROCESSING_IFD_POINTER, 8256, IFD_FORMAT_BYTE) }; - // List of indices of the indicated tag groups according to the EXIF_POINTER_TAGS - private static final int[] EXIF_POINTER_TAG_HINTS = new int[] { - IFD_PREVIEW_HINT, IFD_EXIF_HINT, IFD_GPS_HINT, IFD_INTEROPERABILITY_HINT, - ORF_CAMERA_SETTINGS_HINT, ORF_IMAGE_PROCESSING_HINT - }; + // Tags for indicating the thumbnail offset and length private static final ExifTag JPEG_INTERCHANGE_FORMAT_TAG = new ExifTag(TAG_JPEG_INTERCHANGE_FORMAT, 513, IFD_FORMAT_ULONG); @@ -1210,6 +1216,8 @@ public class ExifInterface { private static final HashSet<String> sTagSetForCompatibility = new HashSet<>(Arrays.asList( TAG_F_NUMBER, TAG_DIGITAL_ZOOM_RATIO, TAG_EXPOSURE_TIME, TAG_SUBJECT_DISTANCE, TAG_GPS_TIMESTAMP)); + // Mappings from tag number to IFD type for pointer tags. + private static final HashMap sExifPointerTagMap = new HashMap(); // See JPEG File Interchange Format Version 1.02. // The following values are defined for handling JPEG streams. In this implementation, we are @@ -1257,27 +1265,32 @@ public class ExifInterface { private static final int IMAGE_TYPE_SRW = 11; static { - System.loadLibrary("media_jni"); - nativeInitRaw(); sFormatter = new SimpleDateFormat("yyyy:MM:dd HH:mm:ss"); sFormatter.setTimeZone(TimeZone.getTimeZone("UTC")); // Build up the hash tables to look up Exif tags for reading Exif tags. - for (int hint = 0; hint < EXIF_TAGS.length; ++hint) { - sExifTagMapsForReading[hint] = new HashMap(); - sExifTagMapsForWriting[hint] = new HashMap(); - for (ExifTag tag : EXIF_TAGS[hint]) { - sExifTagMapsForReading[hint].put(tag.number, tag); - sExifTagMapsForWriting[hint].put(tag.name, tag); - } - } + for (int ifdType = 0; ifdType < EXIF_TAGS.length; ++ifdType) { + sExifTagMapsForReading[ifdType] = new HashMap(); + sExifTagMapsForWriting[ifdType] = new HashMap(); + for (ExifTag tag : EXIF_TAGS[ifdType]) { + sExifTagMapsForReading[ifdType].put(tag.number, tag); + sExifTagMapsForWriting[ifdType].put(tag.name, tag); + } + } + + // Build up the hash table to look up Exif pointer tags. + sExifPointerTagMap.put(EXIF_POINTER_TAGS[0].number, IFD_TYPE_PREVIEW); // 330 + sExifPointerTagMap.put(EXIF_POINTER_TAGS[1].number, IFD_TYPE_EXIF); // 34665 + sExifPointerTagMap.put(EXIF_POINTER_TAGS[2].number, IFD_TYPE_GPS); // 34853 + sExifPointerTagMap.put(EXIF_POINTER_TAGS[3].number, IFD_TYPE_INTEROPERABILITY); // 40965 + sExifPointerTagMap.put(EXIF_POINTER_TAGS[4].number, IFD_TYPE_ORF_CAMERA_SETTINGS); // 8224 + sExifPointerTagMap.put(EXIF_POINTER_TAGS[5].number, IFD_TYPE_ORF_IMAGE_PROCESSING); // 8256 } private final String mFilename; private final FileDescriptor mSeekableFileDescriptor; private final AssetManager.AssetInputStream mAssetInputStream; private final boolean mIsInputStream; - private boolean mIsRaw; private int mMimeType; private final HashMap[] mAttributes = new HashMap[EXIF_TAGS.length]; private ByteOrder mExifByteOrder = ByteOrder.BIG_ENDIAN; @@ -1507,7 +1520,7 @@ public class ExifInterface { } for (int i = 0 ; i < EXIF_TAGS.length; ++i) { - if (i == IFD_THUMBNAIL_HINT && !mHasThumbnail) { + if (i == IFD_TYPE_THUMBNAIL && !mHasThumbnail) { continue; } final Object obj = sExifTagMapsForWriting[i].get(tag); @@ -1660,71 +1673,44 @@ public class ExifInterface { mAttributes[i] = new HashMap(); } - if (HANDLE_RAW) { - // Check file type - in = new BufferedInputStream(in, SIGNATURE_CHECK_SIZE); - mMimeType = getMimeType((BufferedInputStream) in); + // Check file type + in = new BufferedInputStream(in, SIGNATURE_CHECK_SIZE); + mMimeType = getMimeType((BufferedInputStream) in); - switch (mMimeType) { - case IMAGE_TYPE_JPEG: { - getJpegAttributes(in, 0, IFD_TIFF_HINT); // 0 is offset - break; - } - case IMAGE_TYPE_RAF: { - getRafAttributes(in); - break; - } - case IMAGE_TYPE_ORF: { - getOrfAttributes(in); - break; - } - case IMAGE_TYPE_RW2: { - getRw2Attributes(in); - break; - } - case IMAGE_TYPE_ARW: - case IMAGE_TYPE_CR2: - case IMAGE_TYPE_DNG: - case IMAGE_TYPE_NEF: - case IMAGE_TYPE_NRW: - case IMAGE_TYPE_PEF: - case IMAGE_TYPE_SRW: - case IMAGE_TYPE_UNKNOWN: { - getRawAttributes(in); - break; - } - default: { - break; - } + switch (mMimeType) { + case IMAGE_TYPE_JPEG: { + getJpegAttributes(in, 0, IFD_TYPE_PRIMARY); // 0 is offset + break; } - // Set thumbnail image offset and length - setThumbnailData(in); - } else { - if (mAssetInputStream != null) { - long asset = mAssetInputStream.getNativeAsset(); - if (handleRawResult(nativeGetRawAttributesFromAsset(asset))) { - return; - } - } else if (mSeekableFileDescriptor != null) { - if (handleRawResult(nativeGetRawAttributesFromFileDescriptor( - mSeekableFileDescriptor))) { - return; - } - } else { - in.mark(JPEG_SIGNATURE.length); - byte[] signatureBytes = new byte[JPEG_SIGNATURE.length]; - if (in.read(signatureBytes) != JPEG_SIGNATURE.length) { - throw new EOFException(); - } - in.reset(); - if (!isJpegFormat(signatureBytes) && handleRawResult( - nativeGetRawAttributesFromInputStream(in))) { - return; - } + case IMAGE_TYPE_RAF: { + getRafAttributes(in); + break; + } + case IMAGE_TYPE_ORF: { + getOrfAttributes(in); + break; + } + case IMAGE_TYPE_RW2: { + getRw2Attributes(in); + break; + } + case IMAGE_TYPE_ARW: + case IMAGE_TYPE_CR2: + case IMAGE_TYPE_DNG: + case IMAGE_TYPE_NEF: + case IMAGE_TYPE_NRW: + case IMAGE_TYPE_PEF: + case IMAGE_TYPE_SRW: + case IMAGE_TYPE_UNKNOWN: { + getRawAttributes(in); + break; + } + default: { + break; } - // Process JPEG input stream - getJpegAttributes(in, 0, IFD_TIFF_HINT); } + // Set thumbnail image offset and length + setThumbnailData(in); } catch (IOException e) { // Ignore exceptions in order to keep the compatibility with the old versions of // ExifInterface. @@ -1742,36 +1728,6 @@ public class ExifInterface { } } - private boolean handleRawResult(HashMap map) { - if (map == null) { - if (DEBUG) { - Log.d(TAG, "Raw image file not detected"); - } - return false; - } - - // Mark for disabling the save feature. - mIsRaw = true; - - String value = (String) map.remove(TAG_HAS_THUMBNAIL); - mHasThumbnail = value != null && value.equalsIgnoreCase("true"); - value = (String) map.remove(TAG_THUMBNAIL_OFFSET); - if (value != null) { - mThumbnailOffset = Integer.parseInt(value); - } - value = (String) map.remove(TAG_THUMBNAIL_LENGTH); - if (value != null) { - mThumbnailLength = Integer.parseInt(value); - } - mThumbnailBytes = (byte[]) map.remove(TAG_THUMBNAIL_DATA); - - for (Map.Entry entry : (Set<Map.Entry>) map.entrySet()) { - setAttribute((String) entry.getKey(), (String) entry.getValue()); - } - - return true; - } - private static boolean isSeekableFD(FileDescriptor fd) throws IOException { try { Os.lseek(fd, 0, OsConstants.SEEK_CUR); @@ -1800,9 +1756,9 @@ public class ExifInterface { * and make a single call rather than multiple calls for each attribute. */ public void saveAttributes() throws IOException { - if (mIsRaw) { + if (mMimeType != IMAGE_TYPE_JPEG) { throw new UnsupportedOperationException( - "ExifInterface does not support saving attributes on RAW formats."); + "ExifInterface only supports saving attributes on JPEG formats."); } if (mIsInputStream || (mSeekableFileDescriptor == null && mFilename == null)) { throw new UnsupportedOperationException( @@ -1955,9 +1911,9 @@ public class ExifInterface { } ExifAttribute imageLengthAttribute = - (ExifAttribute) mAttributes[IFD_THUMBNAIL_HINT].get(TAG_IMAGE_LENGTH); + (ExifAttribute) mAttributes[IFD_TYPE_THUMBNAIL].get(TAG_IMAGE_LENGTH); ExifAttribute imageWidthAttribute = - (ExifAttribute) mAttributes[IFD_THUMBNAIL_HINT].get(TAG_IMAGE_WIDTH); + (ExifAttribute) mAttributes[IFD_TYPE_THUMBNAIL].get(TAG_IMAGE_WIDTH); if (imageLengthAttribute != null && imageWidthAttribute != null) { int imageLength = imageLengthAttribute.getIntValue(mExifByteOrder); int imageWidth = imageWidthAttribute.getIntValue(mExifByteOrder); @@ -2226,9 +2182,9 @@ public class ExifInterface { * * @param inputStream The input stream that starts with the JPEG data. * @param jpegOffset The offset value in input stream for JPEG data. - * @param imageTypes The image type from which to retrieve metadata. Use IFD_TIFF_HINT for - * primary image, IFD_PREVIEW_HINT for preview image, and - * IFD_THUMBNAIL_HINT for thumbnail image. + * @param imageTypes The image type from which to retrieve metadata. Use IFD_TYPE_PRIMARY for + * primary image, IFD_TYPE_PREVIEW for preview image, and + * IFD_TYPE_THUMBNAIL for thumbnail image. * @throws IOException If the data contains invalid JPEG markers, offsets, or length values. */ private void getJpegAttributes(InputStream inputStream, int jpegOffset, int imageType) @@ -2329,7 +2285,7 @@ public class ExifInterface { } length = 0; if (getAttribute(TAG_USER_COMMENT) == null) { - mAttributes[IFD_EXIF_HINT].put(TAG_USER_COMMENT, ExifAttribute.createString( + mAttributes[IFD_TYPE_EXIF].put(TAG_USER_COMMENT, ExifAttribute.createString( new String(bytes, ASCII))); } break; @@ -2389,12 +2345,12 @@ public class ExifInterface { parseTiffHeaders(dataInputStream, exifBytes.length); // Read TIFF image file directories. See JEITA CP-3451C Section 4.5.2. Figure 6. - readImageFileDirectory(dataInputStream, IFD_TIFF_HINT); + readImageFileDirectory(dataInputStream, IFD_TYPE_PRIMARY); // Update ImageLength/Width tags for all image data. - updateImageSizeValues(in, IFD_TIFF_HINT); - updateImageSizeValues(in, IFD_PREVIEW_HINT); - updateImageSizeValues(in, IFD_THUMBNAIL_HINT); + updateImageSizeValues(in, IFD_TYPE_PRIMARY); + updateImageSizeValues(in, IFD_TYPE_PREVIEW); + updateImageSizeValues(in, IFD_TYPE_THUMBNAIL); // Check if each image data is in valid position. validateImages(in); @@ -2403,7 +2359,7 @@ public class ExifInterface { // PEF files contain a MakerNote data, which contains the data for ColorSpace tag. // See http://lclevy.free.fr/raw/ and piex.cc PefGetPreviewData() ExifAttribute makerNoteAttribute = - (ExifAttribute) mAttributes[IFD_EXIF_HINT].get(TAG_MAKER_NOTE); + (ExifAttribute) mAttributes[IFD_TYPE_EXIF].get(TAG_MAKER_NOTE); if (makerNoteAttribute != null) { // Create an ordered DataInputStream for MakerNote ByteOrderAwarenessDataInputStream makerNoteDataInputStream = @@ -2414,13 +2370,13 @@ public class ExifInterface { makerNoteDataInputStream.seek(PEF_MAKER_NOTE_SKIP_SIZE); // Read IFD data from MakerNote - readImageFileDirectory(makerNoteDataInputStream, PEF_HINT); + readImageFileDirectory(makerNoteDataInputStream, IFD_TYPE_PEF); // Update ColorSpace tag ExifAttribute colorSpaceAttribute = - (ExifAttribute) mAttributes[PEF_HINT].get(TAG_COLOR_SPACE); + (ExifAttribute) mAttributes[IFD_TYPE_PEF].get(TAG_COLOR_SPACE); if (colorSpaceAttribute != null) { - mAttributes[IFD_EXIF_HINT].put(TAG_COLOR_SPACE, colorSpaceAttribute); + mAttributes[IFD_TYPE_EXIF].put(TAG_COLOR_SPACE, colorSpaceAttribute); } } } @@ -2453,7 +2409,7 @@ public class ExifInterface { in.reset(); // Retrieve JPEG image metadata - getJpegAttributes(in, rafJpegOffset, IFD_PREVIEW_HINT); + getJpegAttributes(in, rafJpegOffset, IFD_TYPE_PREVIEW); // Skip to CFA header offset. // A while loop is used because the skip method may not be able to skip the requested amount @@ -2490,8 +2446,8 @@ public class ExifInterface { ExifAttribute.createUShort(imageLength, mExifByteOrder); ExifAttribute imageWidthAttribute = ExifAttribute.createUShort(imageWidth, mExifByteOrder); - mAttributes[IFD_TIFF_HINT].put(TAG_IMAGE_LENGTH, imageLengthAttribute); - mAttributes[IFD_TIFF_HINT].put(TAG_IMAGE_WIDTH, imageWidthAttribute); + mAttributes[IFD_TYPE_PRIMARY].put(TAG_IMAGE_LENGTH, imageLengthAttribute); + mAttributes[IFD_TYPE_PRIMARY].put(TAG_IMAGE_WIDTH, imageWidthAttribute); if (DEBUG) { Log.d(TAG, "Updated to length: " + imageLength + ", width: " + imageWidth); } @@ -2520,7 +2476,7 @@ public class ExifInterface { // proprietary tags and therefore does not have offical documentation // See GetOlympusPreviewImage() in piex.cc & http://www.exiv2.org/tags-olympus.html ExifAttribute makerNoteAttribute = - (ExifAttribute) mAttributes[IFD_EXIF_HINT].get(TAG_MAKER_NOTE); + (ExifAttribute) mAttributes[IFD_TYPE_EXIF].get(TAG_MAKER_NOTE); if (makerNoteAttribute != null) { // Create an ordered DataInputStream for MakerNote ByteOrderAwarenessDataInputStream makerNoteDataInputStream = @@ -2542,18 +2498,18 @@ public class ExifInterface { } // Read IFD data from MakerNote - readImageFileDirectory(makerNoteDataInputStream, ORF_MAKER_NOTE_HINT); + readImageFileDirectory(makerNoteDataInputStream, IFD_TYPE_ORF_MAKER_NOTE); // Retrieve & update preview image offset & length values ExifAttribute imageLengthAttribute = (ExifAttribute) - mAttributes[ORF_CAMERA_SETTINGS_HINT].get(TAG_ORF_PREVIEW_IMAGE_START); + mAttributes[IFD_TYPE_ORF_CAMERA_SETTINGS].get(TAG_ORF_PREVIEW_IMAGE_START); ExifAttribute bitsPerSampleAttribute = (ExifAttribute) - mAttributes[ORF_CAMERA_SETTINGS_HINT].get(TAG_ORF_PREVIEW_IMAGE_LENGTH); + mAttributes[IFD_TYPE_ORF_CAMERA_SETTINGS].get(TAG_ORF_PREVIEW_IMAGE_LENGTH); if (imageLengthAttribute != null && bitsPerSampleAttribute != null) { - mAttributes[IFD_PREVIEW_HINT].put(TAG_JPEG_INTERCHANGE_FORMAT, + mAttributes[IFD_TYPE_PREVIEW].put(TAG_JPEG_INTERCHANGE_FORMAT, imageLengthAttribute); - mAttributes[IFD_PREVIEW_HINT].put(TAG_JPEG_INTERCHANGE_FORMAT_LENGTH, + mAttributes[IFD_TYPE_PREVIEW].put(TAG_JPEG_INTERCHANGE_FORMAT_LENGTH, bitsPerSampleAttribute); } @@ -2561,7 +2517,7 @@ public class ExifInterface { // Retrieve primary image length & width values // See piex.cc GetOlympusPreviewImage() ExifAttribute aspectFrameAttribute = (ExifAttribute) - mAttributes[ORF_IMAGE_PROCESSING_HINT].get(TAG_ORF_ASPECT_FRAME); + mAttributes[IFD_TYPE_ORF_IMAGE_PROCESSING].get(TAG_ORF_ASPECT_FRAME); if (aspectFrameAttribute != null) { int[] aspectFrameValues = new int[4]; aspectFrameValues = (int[]) aspectFrameAttribute.getValue(mExifByteOrder); @@ -2580,8 +2536,8 @@ public class ExifInterface { ExifAttribute primaryImageLengthAttribute = ExifAttribute.createUShort(primaryImageLength, mExifByteOrder); - mAttributes[IFD_TIFF_HINT].put(TAG_IMAGE_WIDTH, primaryImageWidthAttribute); - mAttributes[IFD_TIFF_HINT].put(TAG_IMAGE_LENGTH, primaryImageLengthAttribute); + mAttributes[IFD_TYPE_PRIMARY].put(TAG_IMAGE_WIDTH, primaryImageWidthAttribute); + mAttributes[IFD_TYPE_PRIMARY].put(TAG_IMAGE_LENGTH, primaryImageLengthAttribute); } } } @@ -2596,47 +2552,19 @@ public class ExifInterface { // Retrieve preview and/or thumbnail image data ExifAttribute jpgFromRawAttribute = - (ExifAttribute) mAttributes[IFD_TIFF_HINT].get(TAG_RW2_JPG_FROM_RAW); + (ExifAttribute) mAttributes[IFD_TYPE_PRIMARY].get(TAG_RW2_JPG_FROM_RAW); if (jpgFromRawAttribute != null) { - getJpegAttributes(in, mRw2JpgFromRawOffset, IFD_PREVIEW_HINT); + getJpegAttributes(in, mRw2JpgFromRawOffset, IFD_TYPE_PREVIEW); } // Set ISO tag value if necessary ExifAttribute rw2IsoAttribute = - (ExifAttribute) mAttributes[IFD_TIFF_HINT].get(TAG_RW2_ISO); + (ExifAttribute) mAttributes[IFD_TYPE_PRIMARY].get(TAG_RW2_ISO); ExifAttribute exifIsoAttribute = - (ExifAttribute) mAttributes[IFD_EXIF_HINT].get(TAG_ISO_SPEED_RATINGS); + (ExifAttribute) mAttributes[IFD_TYPE_EXIF].get(TAG_ISO_SPEED_RATINGS); if (rw2IsoAttribute != null && exifIsoAttribute == null) { // Place this attribute only if it doesn't exist - mAttributes[IFD_EXIF_HINT].put(TAG_ISO_SPEED_RATINGS, rw2IsoAttribute); - } - } - - // PEF is TIFF-based and contains 3 IFDs. It also contains a MakerNote data, which contains the - // ColorSpace tag data. - // See http://lclevy.free.fr/raw/ and piex.cc PefGetPreviewData() - private void getPefAttributes(InputStream in) throws IOException { - // Retrieve ColorSpace tag - ExifAttribute makerNoteAttribute = - (ExifAttribute) mAttributes[IFD_EXIF_HINT].get(TAG_MAKER_NOTE); - if (makerNoteAttribute != null) { - // Create an ordered DataInputStream for MakerNote - ByteOrderAwarenessDataInputStream makerNoteDataInputStream = - new ByteOrderAwarenessDataInputStream(makerNoteAttribute.bytes); - makerNoteDataInputStream.setByteOrder(mExifByteOrder); - - // Seek to MakerNote data - makerNoteDataInputStream.seek(PEF_MAKER_NOTE_SKIP_SIZE); - - // Read IFD data from MakerNote - readImageFileDirectory(makerNoteDataInputStream, PEF_HINT); - - // Update ColorSpace tag - ExifAttribute colorSpaceAttribute = - (ExifAttribute) mAttributes[PEF_HINT].get(TAG_COLOR_SPACE); - if (colorSpaceAttribute != null) { - mAttributes[IFD_EXIF_HINT].put(TAG_COLOR_SPACE, colorSpaceAttribute); - } + mAttributes[IFD_TYPE_EXIF].put(TAG_ISO_SPEED_RATINGS, rw2IsoAttribute); } } @@ -2754,25 +2682,25 @@ public class ExifInterface { // The value of DATETIME tag has the same value of DATETIME_ORIGINAL tag. String valueOfDateTimeOriginal = getAttribute(TAG_DATETIME_ORIGINAL); if (valueOfDateTimeOriginal != null) { - mAttributes[IFD_TIFF_HINT].put(TAG_DATETIME, + mAttributes[IFD_TYPE_PRIMARY].put(TAG_DATETIME, ExifAttribute.createString(valueOfDateTimeOriginal)); } // Add the default value. if (getAttribute(TAG_IMAGE_WIDTH) == null) { - mAttributes[IFD_TIFF_HINT].put(TAG_IMAGE_WIDTH, + mAttributes[IFD_TYPE_PRIMARY].put(TAG_IMAGE_WIDTH, ExifAttribute.createULong(0, mExifByteOrder)); } if (getAttribute(TAG_IMAGE_LENGTH) == null) { - mAttributes[IFD_TIFF_HINT].put(TAG_IMAGE_LENGTH, + mAttributes[IFD_TYPE_PRIMARY].put(TAG_IMAGE_LENGTH, ExifAttribute.createULong(0, mExifByteOrder)); } if (getAttribute(TAG_ORIENTATION) == null) { - mAttributes[IFD_TIFF_HINT].put(TAG_ORIENTATION, + mAttributes[IFD_TYPE_PRIMARY].put(TAG_ORIENTATION, ExifAttribute.createULong(0, mExifByteOrder)); } if (getAttribute(TAG_LIGHT_SOURCE) == null) { - mAttributes[IFD_EXIF_HINT].put(TAG_LIGHT_SOURCE, + mAttributes[IFD_TYPE_EXIF].put(TAG_LIGHT_SOURCE, ExifAttribute.createULong(0, mExifByteOrder)); } } @@ -2824,8 +2752,8 @@ public class ExifInterface { } // Reads image file directory, which is a tag group in EXIF. - private void readImageFileDirectory(ByteOrderAwarenessDataInputStream dataInputStream, int hint) - throws IOException { + private void readImageFileDirectory(ByteOrderAwarenessDataInputStream dataInputStream, + @IfdType int ifdType) throws IOException { if (dataInputStream.peek() + 2 > dataInputStream.mLength) { // Return if there is no data from the offset. return; @@ -2850,12 +2778,12 @@ public class ExifInterface { long nextEntryOffset = dataInputStream.peek() + 4; // Look up a corresponding tag from tag number - ExifTag tag = (ExifTag) sExifTagMapsForReading[hint].get(tagNumber); + ExifTag tag = (ExifTag) sExifTagMapsForReading[ifdType].get(tagNumber); if (DEBUG) { - Log.d(TAG, String.format("hint: %d, tagNumber: %d, tagName: %s, dataFormat: %d, " + - "numberOfComponents: %d", hint, tagNumber, tag != null ? tag.name : null, - dataFormat, numberOfComponents)); + Log.d(TAG, String.format("ifdType: %d, tagNumber: %d, tagName: %s, dataFormat: %d, " + + "numberOfComponents: %d", ifdType, tagNumber, + tag != null ? tag.name : null, dataFormat, numberOfComponents)); } if (tag == null || dataFormat <= 0 || @@ -2882,7 +2810,8 @@ public class ExifInterface { if (tag.name == TAG_MAKER_NOTE) { // Save offset value for reading thumbnail mOrfMakerNoteOffset = offset; - } else if (hint == ORF_MAKER_NOTE_HINT && tag.name == TAG_ORF_THUMBNAIL_IMAGE) { + } else if (ifdType == IFD_TYPE_ORF_MAKER_NOTE + && tag.name == TAG_ORF_THUMBNAIL_IMAGE) { // Retrieve & update values for thumbnail offset and length values for ORF mOrfThumbnailOffset = offset; mOrfThumbnailLength = numberOfComponents; @@ -2894,10 +2823,10 @@ public class ExifInterface { ExifAttribute jpegInterchangeFormatLengthAttribute = ExifAttribute.createULong(mOrfThumbnailLength, mExifByteOrder); - mAttributes[IFD_THUMBNAIL_HINT].put(TAG_COMPRESSION, compressionAttribute); - mAttributes[IFD_THUMBNAIL_HINT].put(TAG_JPEG_INTERCHANGE_FORMAT, + mAttributes[IFD_TYPE_THUMBNAIL].put(TAG_COMPRESSION, compressionAttribute); + mAttributes[IFD_TYPE_THUMBNAIL].put(TAG_JPEG_INTERCHANGE_FORMAT, jpegInterchangeFormatAttribute); - mAttributes[IFD_THUMBNAIL_HINT].put(TAG_JPEG_INTERCHANGE_FORMAT_LENGTH, + mAttributes[IFD_TYPE_THUMBNAIL].put(TAG_JPEG_INTERCHANGE_FORMAT_LENGTH, jpegInterchangeFormatLengthAttribute); } } else if (mMimeType == IMAGE_TYPE_RW2) { @@ -2916,12 +2845,12 @@ public class ExifInterface { } // Recursively parse IFD when a IFD pointer tag appears. - int innerIfdHint = getIfdHintFromTagNumber(tagNumber); + Object nextIfdType = sExifPointerTagMap.get(tagNumber); if (DEBUG) { - Log.d(TAG, "innerIfdHint: " + innerIfdHint + " byteCount: " + byteCount); + Log.d(TAG, "nextIfdType: " + nextIfdType + " byteCount: " + byteCount); } - if (innerIfdHint >= 0) { + if (nextIfdType != null) { long offset = -1L; // Get offset from data field switch (dataFormat) { @@ -2952,7 +2881,7 @@ public class ExifInterface { } if (offset > 0L && offset < dataInputStream.mLength) { dataInputStream.seek(offset); - readImageFileDirectory(dataInputStream, innerIfdHint); + readImageFileDirectory(dataInputStream, (int) nextIfdType); } else { Log.w(TAG, "Skip jump into the IFD since its offset is invalid: " + offset); } @@ -2964,7 +2893,7 @@ public class ExifInterface { byte[] bytes = new byte[byteCount]; dataInputStream.readFully(bytes); ExifAttribute attribute = new ExifAttribute(dataFormat, numberOfComponents, bytes); - mAttributes[hint].put(tag.name, attribute); + mAttributes[ifdType].put(tag.name, attribute); // DNG files have a DNG Version tag specifying the version of specifications that the // image file is following. @@ -2998,11 +2927,11 @@ public class ExifInterface { // since the first IFD offset is at least 8. if (nextIfdOffset > 8 && nextIfdOffset < dataInputStream.mLength) { dataInputStream.seek(nextIfdOffset); - if (mAttributes[IFD_THUMBNAIL_HINT].isEmpty()) { + if (mAttributes[IFD_TYPE_THUMBNAIL].isEmpty()) { // Do not overwrite thumbnail IFD data if it alreay exists. - readImageFileDirectory(dataInputStream, IFD_THUMBNAIL_HINT); - } else if (mAttributes[IFD_PREVIEW_HINT].isEmpty()) { - readImageFileDirectory(dataInputStream, IFD_PREVIEW_HINT); + readImageFileDirectory(dataInputStream, IFD_TYPE_THUMBNAIL); + } else if (mAttributes[IFD_TYPE_PREVIEW].isEmpty()) { + readImageFileDirectory(dataInputStream, IFD_TYPE_PREVIEW); } } } @@ -3037,7 +2966,7 @@ public class ExifInterface { // Sets thumbnail offset & length attributes based on JpegInterchangeFormat or StripOffsets tags private void setThumbnailData(InputStream in) throws IOException { - HashMap thumbnailData = mAttributes[IFD_THUMBNAIL_HINT]; + HashMap thumbnailData = mAttributes[IFD_TYPE_THUMBNAIL]; ExifAttribute compressionAttribute = (ExifAttribute) thumbnailData.get(TAG_COMPRESSION); @@ -3207,21 +3136,21 @@ public class ExifInterface { // Validate primary, preview, thumbnail image data by comparing image size private void validateImages(InputStream in) throws IOException { // Swap images based on size (primary > preview > thumbnail) - swapBasedOnImageSize(IFD_TIFF_HINT, IFD_PREVIEW_HINT); - swapBasedOnImageSize(IFD_TIFF_HINT, IFD_THUMBNAIL_HINT); - swapBasedOnImageSize(IFD_PREVIEW_HINT, IFD_THUMBNAIL_HINT); + swapBasedOnImageSize(IFD_TYPE_PRIMARY, IFD_TYPE_PREVIEW); + swapBasedOnImageSize(IFD_TYPE_PRIMARY, IFD_TYPE_THUMBNAIL); + swapBasedOnImageSize(IFD_TYPE_PREVIEW, IFD_TYPE_THUMBNAIL); // Check whether thumbnail image exists and whether preview image satisfies the thumbnail // image requirements - if (mAttributes[IFD_THUMBNAIL_HINT].isEmpty()) { - if (isThumbnail(mAttributes[IFD_PREVIEW_HINT])) { - mAttributes[IFD_THUMBNAIL_HINT] = mAttributes[IFD_PREVIEW_HINT]; - mAttributes[IFD_PREVIEW_HINT] = new HashMap(); + if (mAttributes[IFD_TYPE_THUMBNAIL].isEmpty()) { + if (isThumbnail(mAttributes[IFD_TYPE_PREVIEW])) { + mAttributes[IFD_TYPE_THUMBNAIL] = mAttributes[IFD_TYPE_PREVIEW]; + mAttributes[IFD_TYPE_PREVIEW] = new HashMap(); } } // Check if the thumbnail image satisfies the thumbnail size requirements - if (!isThumbnail(mAttributes[IFD_THUMBNAIL_HINT])) { + if (!isThumbnail(mAttributes[IFD_TYPE_THUMBNAIL])) { Log.d(TAG, "No image meets the size requirements of a thumbnail image."); } } @@ -3305,9 +3234,9 @@ public class ExifInterface { if (newSubfileTypeValue == ORIGINAL_RESOLUTION_IMAGE) { // Update only for the primary image (OriginalResolutionImage) ExifAttribute pixelXDimAttribute = - (ExifAttribute) mAttributes[IFD_EXIF_HINT].get(TAG_PIXEL_X_DIMENSION); + (ExifAttribute) mAttributes[IFD_TYPE_EXIF].get(TAG_PIXEL_X_DIMENSION); ExifAttribute pixelYDimAttribute = - (ExifAttribute) mAttributes[IFD_EXIF_HINT].get(TAG_PIXEL_Y_DIMENSION); + (ExifAttribute) mAttributes[IFD_TYPE_EXIF].get(TAG_PIXEL_Y_DIMENSION); if (pixelXDimAttribute != null && pixelYDimAttribute != null) { mAttributes[imageType].put(TAG_IMAGE_WIDTH, pixelXDimAttribute); @@ -3320,16 +3249,6 @@ public class ExifInterface { } } - // Gets the corresponding IFD group index of the given tag number for writing Exif Tags. - private static int getIfdHintFromTagNumber(int tagNumber) { - for (int i = 0; i < EXIF_POINTER_TAG_HINTS.length; ++i) { - if (EXIF_POINTER_TAGS[i].number == tagNumber) { - return EXIF_POINTER_TAG_HINTS[i]; - } - } - return -1; - } - // Writes an Exif segment into the given output stream. private int writeExifSegment(ByteOrderAwarenessDataOutputStream dataOutputStream, int exifOffsetFromBeginning) throws IOException { @@ -3346,33 +3265,33 @@ public class ExifInterface { removeAttribute(JPEG_INTERCHANGE_FORMAT_LENGTH_TAG.name); // Remove null value tags. - for (int hint = 0; hint < EXIF_TAGS.length; ++hint) { - for (Object obj : mAttributes[hint].entrySet().toArray()) { + for (int ifdType = 0; ifdType < EXIF_TAGS.length; ++ifdType) { + for (Object obj : mAttributes[ifdType].entrySet().toArray()) { final Map.Entry entry = (Map.Entry) obj; if (entry.getValue() == null) { - mAttributes[hint].remove(entry.getKey()); + mAttributes[ifdType].remove(entry.getKey()); } } } // Add IFD pointer tags. The next offset of primary image TIFF IFD will have thumbnail IFD // offset when there is one or more tags in the thumbnail IFD. - if (!mAttributes[IFD_EXIF_HINT].isEmpty()) { - mAttributes[IFD_TIFF_HINT].put(EXIF_POINTER_TAGS[1].name, + if (!mAttributes[IFD_TYPE_EXIF].isEmpty()) { + mAttributes[IFD_TYPE_PRIMARY].put(EXIF_POINTER_TAGS[1].name, ExifAttribute.createULong(0, mExifByteOrder)); } - if (!mAttributes[IFD_GPS_HINT].isEmpty()) { - mAttributes[IFD_TIFF_HINT].put(EXIF_POINTER_TAGS[2].name, + if (!mAttributes[IFD_TYPE_GPS].isEmpty()) { + mAttributes[IFD_TYPE_PRIMARY].put(EXIF_POINTER_TAGS[2].name, ExifAttribute.createULong(0, mExifByteOrder)); } - if (!mAttributes[IFD_INTEROPERABILITY_HINT].isEmpty()) { - mAttributes[IFD_EXIF_HINT].put(EXIF_POINTER_TAGS[3].name, + if (!mAttributes[IFD_TYPE_INTEROPERABILITY].isEmpty()) { + mAttributes[IFD_TYPE_EXIF].put(EXIF_POINTER_TAGS[3].name, ExifAttribute.createULong(0, mExifByteOrder)); } if (mHasThumbnail) { - mAttributes[IFD_THUMBNAIL_HINT].put(JPEG_INTERCHANGE_FORMAT_TAG.name, + mAttributes[IFD_TYPE_THUMBNAIL].put(JPEG_INTERCHANGE_FORMAT_TAG.name, ExifAttribute.createULong(0, mExifByteOrder)); - mAttributes[IFD_THUMBNAIL_HINT].put(JPEG_INTERCHANGE_FORMAT_LENGTH_TAG.name, + mAttributes[IFD_TYPE_THUMBNAIL].put(JPEG_INTERCHANGE_FORMAT_LENGTH_TAG.name, ExifAttribute.createULong(mThumbnailLength, mExifByteOrder)); } @@ -3392,15 +3311,15 @@ public class ExifInterface { // Calculate IFD offsets. int position = 8; - for (int hint = 0; hint < EXIF_TAGS.length; ++hint) { - if (!mAttributes[hint].isEmpty()) { - ifdOffsets[hint] = position; - position += 2 + mAttributes[hint].size() * 12 + 4 + ifdDataSizes[hint]; + for (int ifdType = 0; ifdType < EXIF_TAGS.length; ++ifdType) { + if (!mAttributes[ifdType].isEmpty()) { + ifdOffsets[ifdType] = position; + position += 2 + mAttributes[ifdType].size() * 12 + 4 + ifdDataSizes[ifdType]; } } if (mHasThumbnail) { int thumbnailOffset = position; - mAttributes[IFD_THUMBNAIL_HINT].put(JPEG_INTERCHANGE_FORMAT_TAG.name, + mAttributes[IFD_TYPE_THUMBNAIL].put(JPEG_INTERCHANGE_FORMAT_TAG.name, ExifAttribute.createULong(thumbnailOffset, mExifByteOrder)); mThumbnailOffset = exifOffsetFromBeginning + thumbnailOffset; position += mThumbnailLength; @@ -3417,17 +3336,17 @@ public class ExifInterface { } // Update IFD pointer tags with the calculated offsets. - if (!mAttributes[IFD_EXIF_HINT].isEmpty()) { - mAttributes[IFD_TIFF_HINT].put(EXIF_POINTER_TAGS[1].name, - ExifAttribute.createULong(ifdOffsets[IFD_EXIF_HINT], mExifByteOrder)); + if (!mAttributes[IFD_TYPE_EXIF].isEmpty()) { + mAttributes[IFD_TYPE_PRIMARY].put(EXIF_POINTER_TAGS[1].name, + ExifAttribute.createULong(ifdOffsets[IFD_TYPE_EXIF], mExifByteOrder)); } - if (!mAttributes[IFD_GPS_HINT].isEmpty()) { - mAttributes[IFD_TIFF_HINT].put(EXIF_POINTER_TAGS[2].name, - ExifAttribute.createULong(ifdOffsets[IFD_GPS_HINT], mExifByteOrder)); + if (!mAttributes[IFD_TYPE_GPS].isEmpty()) { + mAttributes[IFD_TYPE_PRIMARY].put(EXIF_POINTER_TAGS[2].name, + ExifAttribute.createULong(ifdOffsets[IFD_TYPE_GPS], mExifByteOrder)); } - if (!mAttributes[IFD_INTEROPERABILITY_HINT].isEmpty()) { - mAttributes[IFD_EXIF_HINT].put(EXIF_POINTER_TAGS[3].name, ExifAttribute.createULong( - ifdOffsets[IFD_INTEROPERABILITY_HINT], mExifByteOrder)); + if (!mAttributes[IFD_TYPE_INTEROPERABILITY].isEmpty()) { + mAttributes[IFD_TYPE_EXIF].put(EXIF_POINTER_TAGS[3].name, ExifAttribute.createULong( + ifdOffsets[IFD_TYPE_INTEROPERABILITY], mExifByteOrder)); } // Write TIFF Headers. See JEITA CP-3451C Section 4.5.2. Table 1. @@ -3440,17 +3359,18 @@ public class ExifInterface { dataOutputStream.writeUnsignedInt(IFD_OFFSET); // Write IFD groups. See JEITA CP-3451C Section 4.5.8. Figure 9. - for (int hint = 0; hint < EXIF_TAGS.length; ++hint) { - if (!mAttributes[hint].isEmpty()) { + for (int ifdType = 0; ifdType < EXIF_TAGS.length; ++ifdType) { + if (!mAttributes[ifdType].isEmpty()) { // See JEITA CP-3451C Section 4.6.2: IFD structure. // Write entry count - dataOutputStream.writeUnsignedShort(mAttributes[hint].size()); + dataOutputStream.writeUnsignedShort(mAttributes[ifdType].size()); // Write entry info - int dataOffset = ifdOffsets[hint] + 2 + mAttributes[hint].size() * 12 + 4; - for (Map.Entry entry : (Set<Map.Entry>) mAttributes[hint].entrySet()) { + int dataOffset = ifdOffsets[ifdType] + 2 + mAttributes[ifdType].size() * 12 + 4; + for (Map.Entry entry : (Set<Map.Entry>) mAttributes[ifdType].entrySet()) { // Convert tag name to tag number. - final ExifTag tag = (ExifTag) sExifTagMapsForWriting[hint].get(entry.getKey()); + final ExifTag tag = + (ExifTag) sExifTagMapsForWriting[ifdType].get(entry.getKey()); final int tagNumber = tag.number; final ExifAttribute attribute = (ExifAttribute) entry.getValue(); final int size = attribute.size(); @@ -3475,14 +3395,14 @@ public class ExifInterface { // Write the next offset. It writes the offset of thumbnail IFD if there is one or // more tags in the thumbnail IFD when the current IFD is the primary image TIFF // IFD; Otherwise 0. - if (hint == 0 && !mAttributes[IFD_THUMBNAIL_HINT].isEmpty()) { - dataOutputStream.writeUnsignedInt(ifdOffsets[IFD_THUMBNAIL_HINT]); + if (ifdType == 0 && !mAttributes[IFD_TYPE_THUMBNAIL].isEmpty()) { + dataOutputStream.writeUnsignedInt(ifdOffsets[IFD_TYPE_THUMBNAIL]); } else { dataOutputStream.writeUnsignedInt(0); } // Write values of data field exceeding 4 bytes after the next offset. - for (Map.Entry entry : (Set<Map.Entry>) mAttributes[hint].entrySet()) { + for (Map.Entry entry : (Set<Map.Entry>) mAttributes[ifdType].entrySet()) { ExifAttribute attribute = (ExifAttribute) entry.getValue(); if (attribute.bytes.length > 4) { @@ -3809,9 +3729,9 @@ public class ExifInterface { } // Swaps image data based on image size - private void swapBasedOnImageSize(int firstImageHint, int secondImageHint) + private void swapBasedOnImageSize(@IfdType int firstIfdType, @IfdType int secondIfdType) throws IOException { - if (mAttributes[firstImageHint].isEmpty() || mAttributes[secondImageHint].isEmpty()) { + if (mAttributes[firstIfdType].isEmpty() || mAttributes[secondIfdType].isEmpty()) { if (DEBUG) { Log.d(TAG, "Cannot perform swap since only one image data exists"); } @@ -3819,13 +3739,13 @@ public class ExifInterface { } ExifAttribute firstImageLengthAttribute = - (ExifAttribute) mAttributes[firstImageHint].get(TAG_IMAGE_LENGTH); + (ExifAttribute) mAttributes[firstIfdType].get(TAG_IMAGE_LENGTH); ExifAttribute firstImageWidthAttribute = - (ExifAttribute) mAttributes[firstImageHint].get(TAG_IMAGE_WIDTH); + (ExifAttribute) mAttributes[firstIfdType].get(TAG_IMAGE_WIDTH); ExifAttribute secondImageLengthAttribute = - (ExifAttribute) mAttributes[secondImageHint].get(TAG_IMAGE_LENGTH); + (ExifAttribute) mAttributes[secondIfdType].get(TAG_IMAGE_LENGTH); ExifAttribute secondImageWidthAttribute = - (ExifAttribute) mAttributes[secondImageHint].get(TAG_IMAGE_WIDTH); + (ExifAttribute) mAttributes[secondIfdType].get(TAG_IMAGE_WIDTH); if (firstImageLengthAttribute == null || firstImageWidthAttribute == null) { if (DEBUG) { @@ -3843,9 +3763,9 @@ public class ExifInterface { if (firstImageLengthValue < secondImageLengthValue && firstImageWidthValue < secondImageWidthValue) { - HashMap tempMap = mAttributes[firstImageHint]; - mAttributes[firstImageHint] = mAttributes[secondImageHint]; - mAttributes[secondImageHint] = tempMap; + HashMap tempMap = mAttributes[firstIfdType]; + mAttributes[firstIfdType] = mAttributes[secondIfdType]; + mAttributes[secondIfdType] = tempMap; } } } @@ -3864,12 +3784,4 @@ public class ExifInterface { } return false; } - - // JNI methods for RAW formats. - private static native void nativeInitRaw(); - private static native byte[] nativeGetThumbnailFromAsset( - long asset, int thumbnailOffset, int thumbnailLength); - private static native HashMap nativeGetRawAttributesFromAsset(long asset); - private static native HashMap nativeGetRawAttributesFromFileDescriptor(FileDescriptor fd); - private static native HashMap nativeGetRawAttributesFromInputStream(InputStream in); }
\ No newline at end of file diff --git a/media/java/android/media/midi/MidiDeviceServer.java b/media/java/android/media/midi/MidiDeviceServer.java index fbc861579ae0..4c49f677c031 100644 --- a/media/java/android/media/midi/MidiDeviceServer.java +++ b/media/java/android/media/midi/MidiDeviceServer.java @@ -226,10 +226,12 @@ public final class MidiDeviceServer implements Closeable { ParcelFileDescriptor[] pair = ParcelFileDescriptor.createSocketPair( OsConstants.SOCK_SEQPACKET); MidiInputPort inputPort = new MidiInputPort(pair[0], portNumber); - // Configure the server-side socket in non-blocking mode to avoid stalling - // the entire MIDI framework if client app code gets stuck inside 'onSend' - // handler. - IoUtils.setBlocking(pair[0].getFileDescriptor(), false); + // Undo the default blocking-mode of the server-side socket for + // physical devices to avoid stalling the Java device handler if + // client app code gets stuck inside 'onSend' handler. + if (mDeviceInfo.getType() != MidiDeviceInfo.TYPE_VIRTUAL) { + IoUtils.setBlocking(pair[0].getFileDescriptor(), false); + } MidiDispatcher dispatcher = mOutputPortDispatchers[portNumber]; synchronized (dispatcher) { dispatcher.getSender().connect(inputPort); diff --git a/media/jni/Android.mk b/media/jni/Android.mk index 2c28a10a3c4d..dcd50575755c 100644 --- a/media/jni/Android.mk +++ b/media/jni/Android.mk @@ -3,7 +3,6 @@ include $(CLEAR_VARS) LOCAL_SRC_FILES:= \ android_media_AmrInputStream.cpp \ - android_media_ExifInterface.cpp \ android_media_ImageWriter.cpp \ android_media_ImageReader.cpp \ android_media_MediaCrypto.cpp \ diff --git a/media/jni/android_media_ExifInterface.cpp b/media/jni/android_media_ExifInterface.cpp deleted file mode 100644 index 10b317061250..000000000000 --- a/media/jni/android_media_ExifInterface.cpp +++ /dev/null @@ -1,426 +0,0 @@ -/* - * 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. - */ - -//#define LOG_NDEBUG 0 -#define LOG_TAG "ExifInterface_JNI" - -#include "android_media_Utils.h" - -#include "android/graphics/CreateJavaOutputStreamAdaptor.h" -#include "src/piex_types.h" -#include "src/piex.h" - -#include <jni.h> -#include <JNIHelp.h> -#include <androidfw/Asset.h> -#include <android_runtime/AndroidRuntime.h> -#include <android/graphics/Utils.h> -#include <nativehelper/ScopedLocalRef.h> - -#include <utils/Log.h> -#include <utils/String8.h> -#include <utils/KeyedVector.h> - -// ---------------------------------------------------------------------------- - -using namespace android; - -static const char kJpegSignatureChars[] = {(char)0xff, (char)0xd8, (char)0xff}; -static const int kJpegSignatureSize = 3; - -#define FIND_CLASS(var, className) \ - var = env->FindClass(className); \ - LOG_FATAL_IF(! var, "Unable to find class " className); - -#define GET_METHOD_ID(var, clazz, fieldName, fieldDescriptor) \ - var = env->GetMethodID(clazz, fieldName, fieldDescriptor); \ - LOG_FATAL_IF(! var, "Unable to find method " fieldName); - -struct HashMapFields { - jmethodID init; - jmethodID put; -}; - -struct fields_t { - HashMapFields hashMap; - jclass hashMapClassId; -}; - -static fields_t gFields; - -static jobject KeyedVectorToHashMap(JNIEnv *env, KeyedVector<String8, String8> const &map) { - jclass clazz = gFields.hashMapClassId; - jobject hashMap = env->NewObject(clazz, gFields.hashMap.init); - for (size_t i = 0; i < map.size(); ++i) { - jstring jkey = env->NewStringUTF(map.keyAt(i).string()); - jstring jvalue = env->NewStringUTF(map.valueAt(i).string()); - env->CallObjectMethod(hashMap, gFields.hashMap.put, jkey, jvalue); - env->DeleteLocalRef(jkey); - env->DeleteLocalRef(jvalue); - } - return hashMap; -} - -extern "C" { - -// -------------------------- ExifInterface methods --------------------------- - -static void ExifInterface_initRaw(JNIEnv *env) { - jclass clazz; - FIND_CLASS(clazz, "java/util/HashMap"); - gFields.hashMapClassId = static_cast<jclass>(env->NewGlobalRef(clazz)); - - GET_METHOD_ID(gFields.hashMap.init, clazz, "<init>", "()V"); - GET_METHOD_ID(gFields.hashMap.put, clazz, "put", - "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"); -} - -static bool is_asset_stream(const SkStream& stream) { - return stream.hasLength() && stream.hasPosition(); -} - -static jobject ExifInterface_getThumbnailFromAsset( - JNIEnv* env, jclass /* clazz */, jlong jasset, jint jthumbnailOffset, - jint jthumbnailLength) { - Asset* asset = reinterpret_cast<Asset*>(jasset); - std::unique_ptr<AssetStreamAdaptor> stream(new AssetStreamAdaptor(asset)); - - std::unique_ptr<jbyte[]> thumbnailData(new jbyte[(int)jthumbnailLength]); - if (thumbnailData.get() == NULL) { - ALOGI("No memory to get thumbnail"); - return NULL; - } - - // Do not know the current offset. So rewind it. - stream->rewind(); - - // Read thumbnail. - stream->skip((int)jthumbnailOffset); - stream->read((void*)thumbnailData.get(), (int)jthumbnailLength); - - // Copy to the byte array. - jbyteArray byteArray = env->NewByteArray(jthumbnailLength); - env->SetByteArrayRegion(byteArray, 0, jthumbnailLength, thumbnailData.get()); - return byteArray; -} - -static jobject getRawAttributes(JNIEnv* env, SkStream* stream, bool returnThumbnail) { - std::unique_ptr<SkStream> streamDeleter(stream); - - std::unique_ptr<::piex::StreamInterface> piexStream; - if (is_asset_stream(*stream)) { - piexStream.reset(new AssetStream(streamDeleter.release())); - } else { - piexStream.reset(new BufferedStream(streamDeleter.release())); - } - - piex::PreviewImageData image_data; - - if (!GetExifFromRawImage(piexStream.get(), String8("[piex stream]"), image_data)) { - return NULL; - } - - KeyedVector<String8, String8> map; - - if (image_data.thumbnail.length > 0 - && image_data.thumbnail.format == ::piex::Image::kJpegCompressed) { - map.add(String8("HasThumbnail"), String8("true")); - map.add(String8("ThumbnailOffset"), String8::format("%d", image_data.thumbnail.offset)); - map.add(String8("ThumbnailLength"), String8::format("%d", image_data.thumbnail.length)); - } else { - map.add(String8("HasThumbnail"), String8("false")); - } - - map.add( - String8("Orientation"), - String8::format("%u", image_data.exif_orientation)); - map.add( - String8("ImageWidth"), - String8::format("%u", image_data.full_width)); - map.add( - String8("ImageLength"), - String8::format("%u", image_data.full_height)); - - // Current PIEX does not have LightSource information while JPEG version of - // EXIFInterface always declares the light source field. For the - // compatibility, it provides the default value of the light source field. - map.add(String8("LightSource"), String8("0")); - - if (!image_data.maker.empty()) { - map.add(String8("Make"), String8(image_data.maker.c_str())); - } - - if (!image_data.model.empty()) { - map.add(String8("Model"), String8(image_data.model.c_str())); - } - - if (!image_data.date_time.empty()) { - map.add(String8("DateTime"), String8(image_data.date_time.c_str())); - } - - if (image_data.iso) { - map.add( - String8("ISOSpeedRatings"), - String8::format("%u", image_data.iso)); - } - - if (image_data.exposure_time.numerator != 0 - && image_data.exposure_time.denominator != 0) { - double exposureTime = - (double)image_data.exposure_time.numerator - / image_data.exposure_time.denominator; - - const char* format; - if (exposureTime < 0.01) { - format = "%6.4f"; - } else { - format = "%5.3f"; - } - map.add(String8("ExposureTime"), String8::format(format, exposureTime)); - } - - if (image_data.fnumber.numerator != 0 - && image_data.fnumber.denominator != 0) { - double fnumber = - (double)image_data.fnumber.numerator - / image_data.fnumber.denominator; - map.add(String8("FNumber"), String8::format("%5.3f", fnumber)); - } - - if (image_data.focal_length.numerator != 0 - && image_data.focal_length.denominator != 0) { - map.add( - String8("FocalLength"), - String8::format( - "%u/%u", - image_data.focal_length.numerator, - image_data.focal_length.denominator)); - } - - if (image_data.gps.is_valid) { - if (image_data.gps.latitude[0].denominator != 0 - && image_data.gps.latitude[1].denominator != 0 - && image_data.gps.latitude[2].denominator != 0) { - map.add( - String8("GPSLatitude"), - String8::format( - "%u/%u,%u/%u,%u/%u", - image_data.gps.latitude[0].numerator, - image_data.gps.latitude[0].denominator, - image_data.gps.latitude[1].numerator, - image_data.gps.latitude[1].denominator, - image_data.gps.latitude[2].numerator, - image_data.gps.latitude[2].denominator)); - } - - if (image_data.gps.latitude_ref) { - char str[2]; - str[0] = image_data.gps.latitude_ref; - str[1] = 0; - map.add(String8("GPSLatitudeRef"), String8(str)); - } - - if (image_data.gps.longitude[0].denominator != 0 - && image_data.gps.longitude[1].denominator != 0 - && image_data.gps.longitude[2].denominator != 0) { - map.add( - String8("GPSLongitude"), - String8::format( - "%u/%u,%u/%u,%u/%u", - image_data.gps.longitude[0].numerator, - image_data.gps.longitude[0].denominator, - image_data.gps.longitude[1].numerator, - image_data.gps.longitude[1].denominator, - image_data.gps.longitude[2].numerator, - image_data.gps.longitude[2].denominator)); - } - - if (image_data.gps.longitude_ref) { - char str[2]; - str[0] = image_data.gps.longitude_ref; - str[1] = 0; - map.add(String8("GPSLongitudeRef"), String8(str)); - } - - if (image_data.gps.altitude.denominator != 0) { - map.add( - String8("GPSAltitude"), - String8::format("%u/%u", - image_data.gps.altitude.numerator, - image_data.gps.altitude.denominator)); - - map.add( - String8("GPSAltitudeRef"), - String8(image_data.gps.altitude_ref ? "1" : "0")); - } - - if (image_data.gps.time_stamp[0].denominator != 0 - && image_data.gps.time_stamp[1].denominator != 0 - && image_data.gps.time_stamp[2].denominator != 0) { - map.add( - String8("GPSTimeStamp"), - String8::format( - "%02u:%02u:%02u", - image_data.gps.time_stamp[0].numerator - / image_data.gps.time_stamp[0].denominator, - image_data.gps.time_stamp[1].numerator - / image_data.gps.time_stamp[1].denominator, - image_data.gps.time_stamp[2].numerator - / image_data.gps.time_stamp[2].denominator)); - } - - if (!image_data.gps.date_stamp.empty()) { - map.add( - String8("GPSDateStamp"), - String8(image_data.gps.date_stamp.c_str())); - } - } - - jobject hashMap = KeyedVectorToHashMap(env, map); - - if (returnThumbnail) { - std::unique_ptr<jbyte[]> thumbnailData(new jbyte[image_data.thumbnail.length]); - if (thumbnailData.get() == NULL) { - ALOGE("No memory to parse a thumbnail"); - return NULL; - } - jbyteArray jthumbnailByteArray = env->NewByteArray(image_data.thumbnail.length); - if (jthumbnailByteArray == NULL) { - ALOGE("No memory to parse a thumbnail"); - return NULL; - } - piexStream.get()->GetData(image_data.thumbnail.offset, image_data.thumbnail.length, - (uint8_t*)thumbnailData.get()); - env->SetByteArrayRegion( - jthumbnailByteArray, 0, image_data.thumbnail.length, thumbnailData.get()); - jstring jkey = env->NewStringUTF(String8("ThumbnailData")); - env->CallObjectMethod(hashMap, gFields.hashMap.put, jkey, jthumbnailByteArray); - env->DeleteLocalRef(jkey); - env->DeleteLocalRef(jthumbnailByteArray); - } - return hashMap; -} - -static jobject ExifInterface_getRawAttributesFromAsset( - JNIEnv* env, jclass /* clazz */, jlong jasset) { - std::unique_ptr<char[]> jpegSignature(new char[kJpegSignatureSize]); - if (jpegSignature.get() == NULL) { - ALOGE("No enough memory to parse"); - return NULL; - } - - Asset* asset = reinterpret_cast<Asset*>(jasset); - std::unique_ptr<AssetStreamAdaptor> stream(new AssetStreamAdaptor(asset)); - - if (stream.get()->read(jpegSignature.get(), kJpegSignatureSize) != kJpegSignatureSize) { - // Rewind the stream. - stream.get()->rewind(); - - ALOGI("Corrupted image."); - return NULL; - } - - // Rewind the stream. - stream.get()->rewind(); - - if (memcmp(jpegSignature.get(), kJpegSignatureChars, kJpegSignatureSize) == 0) { - ALOGI("Should be a JPEG stream."); - return NULL; - } - - // Try to parse from the given stream. - jobject result = getRawAttributes(env, stream.get(), false); - - // Rewind the stream for the chance to read JPEG. - if (result == NULL) { - stream.get()->rewind(); - } - return result; -} - -static jobject ExifInterface_getRawAttributesFromFileDescriptor( - JNIEnv* env, jclass /* clazz */, jobject jfileDescriptor) { - std::unique_ptr<char[]> jpegSignature(new char[kJpegSignatureSize]); - if (jpegSignature.get() == NULL) { - ALOGE("No enough memory to parse"); - return NULL; - } - - int fd = jniGetFDFromFileDescriptor(env, jfileDescriptor); - if (fd < 0) { - ALOGI("Invalid file descriptor"); - return NULL; - } - - // Restore the file descriptor's offset on exiting this function. - AutoFDSeek autoRestore(fd); - - int dupFd = dup(fd); - - FILE* file = fdopen(dupFd, "r"); - if (file == NULL) { - ALOGI("Failed to open the file descriptor"); - return NULL; - } - - if (fgets(jpegSignature.get(), kJpegSignatureSize, file) == NULL) { - ALOGI("Corrupted image."); - return NULL; - } - - if (memcmp(jpegSignature.get(), kJpegSignatureChars, kJpegSignatureSize) == 0) { - ALOGI("Should be a JPEG stream."); - return NULL; - } - - // Rewind the file descriptor. - fseek(file, 0L, SEEK_SET); - - std::unique_ptr<SkFILEStream> fileStream(new SkFILEStream(file, - SkFILEStream::kCallerPasses_Ownership)); - return getRawAttributes(env, fileStream.get(), false); -} - -static jobject ExifInterface_getRawAttributesFromInputStream( - JNIEnv* env, jclass /* clazz */, jobject jinputStream) { - jbyteArray byteArray = env->NewByteArray(8*1024); - ScopedLocalRef<jbyteArray> scoper(env, byteArray); - std::unique_ptr<SkStream> stream(CreateJavaInputStreamAdaptor(env, jinputStream, scoper.get())); - return getRawAttributes(env, stream.get(), true); -} - -} // extern "C" - -// ---------------------------------------------------------------------------- - -static JNINativeMethod gMethods[] = { - { "nativeInitRaw", "()V", (void *)ExifInterface_initRaw }, - { "nativeGetThumbnailFromAsset", "(JII)[B", (void *)ExifInterface_getThumbnailFromAsset }, - { "nativeGetRawAttributesFromAsset", "(J)Ljava/util/HashMap;", - (void*)ExifInterface_getRawAttributesFromAsset }, - { "nativeGetRawAttributesFromFileDescriptor", "(Ljava/io/FileDescriptor;)Ljava/util/HashMap;", - (void*)ExifInterface_getRawAttributesFromFileDescriptor }, - { "nativeGetRawAttributesFromInputStream", "(Ljava/io/InputStream;)Ljava/util/HashMap;", - (void*)ExifInterface_getRawAttributesFromInputStream }, -}; - -int register_android_media_ExifInterface(JNIEnv *env) { - return AndroidRuntime::registerNativeMethods( - env, - "android/media/ExifInterface", - gMethods, - NELEM(gMethods)); -} diff --git a/media/jni/android_media_MediaPlayer.cpp b/media/jni/android_media_MediaPlayer.cpp index 2fb1a3b9fbcf..ecf733f2459b 100644 --- a/media/jni/android_media_MediaPlayer.cpp +++ b/media/jni/android_media_MediaPlayer.cpp @@ -1090,7 +1090,6 @@ static int register_android_media_MediaPlayer(JNIEnv *env) return AndroidRuntime::registerNativeMethods(env, "android/media/MediaPlayer", gMethods, NELEM(gMethods)); } -extern int register_android_media_ExifInterface(JNIEnv *env); extern int register_android_media_ImageReader(JNIEnv *env); extern int register_android_media_ImageWriter(JNIEnv *env); extern int register_android_media_Crypto(JNIEnv *env); @@ -1222,11 +1221,6 @@ jint JNI_OnLoad(JavaVM* vm, void* /* reserved */) goto bail; } - if (register_android_media_ExifInterface(env) < 0) { - ALOGE("ERROR: ExifInterface native registration failed"); - goto bail; - } - /* success -- return valid version number */ result = JNI_VERSION_1_4; diff --git a/media/tests/MediaFrameworkTest/res/values/exifinterface.xml b/media/tests/MediaFrameworkTest/res/values/exifinterface.xml index 3c5dd3786e7c..8af7de6c9bed 100644 --- a/media/tests/MediaFrameworkTest/res/values/exifinterface.xml +++ b/media/tests/MediaFrameworkTest/res/values/exifinterface.xml @@ -90,8 +90,8 @@ <item>0.0040</item> <item>0.0</item> <item>442/100</item> - <item>0/1</item> - <item>0</item> + <item /> + <item /> <item>1970:01:17</item> <item>53/1,50/1,423/100</item> <item>N</item> diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/ExifInterfaceTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/ExifInterfaceTest.java index 0cc154516ff6..cdd40656297c 100644 --- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/ExifInterfaceTest.java +++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/ExifInterfaceTest.java @@ -252,6 +252,7 @@ public class ExifInterfaceTest extends AndroidTestCase { if (stringValue != null) { stringValue = stringValue.trim(); } + stringValue = (stringValue == "") ? null : stringValue; assertEquals(expectedValue, stringValue); } diff --git a/packages/Keyguard/res/values-af/strings.xml b/packages/Keyguard/res/values-af/strings.xml index 568d82a36750..a3381656ec3d 100644 --- a/packages/Keyguard/res/values-af/strings.xml +++ b/packages/Keyguard/res/values-af/strings.xml @@ -46,11 +46,6 @@ <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM-kaart is gesluit."</string> <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM-kaart is PUK-geslote."</string> <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"Ontsluit tans SIM-kaart…"</string> - <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Patroon ontsluit."</string> - <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"PIN ontsluit."</string> - <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Wagwoord ontsluit."</string> - <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Patroonarea."</string> - <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Sleep-area."</string> <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"PIN-area"</string> <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"SIM-PIN-area"</string> <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"SIM-PUK-area"</string> diff --git a/packages/Keyguard/res/values-am/strings.xml b/packages/Keyguard/res/values-am/strings.xml index 68e9ff3fd824..67fdc321837d 100644 --- a/packages/Keyguard/res/values-am/strings.xml +++ b/packages/Keyguard/res/values-am/strings.xml @@ -46,11 +46,6 @@ <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"ሲም ካርድ ተዘግቷል።"</string> <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"ሲም ካርድ በፒዩኬ ተዘግቷል።"</string> <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"ሲም ካርዱን በመክፈት ላይ…"</string> - <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"በስርዓተ-ጥለት መክፈት።"</string> - <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"በፒን መክፈት።"</string> - <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"በይለፍ ቃል መክፈት።"</string> - <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"የስርዓተ-ጥለት አካባቢ።"</string> - <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"የማንሸራተቻ አካባቢ።"</string> <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"የፒን አካባቢ"</string> <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"የሲም ፒን አካባቢ"</string> <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"የሲም PUK አካባቢ"</string> diff --git a/packages/Keyguard/res/values-ar/strings.xml b/packages/Keyguard/res/values-ar/strings.xml index 09b78e44a2ca..8438699d0319 100644 --- a/packages/Keyguard/res/values-ar/strings.xml +++ b/packages/Keyguard/res/values-ar/strings.xml @@ -46,11 +46,6 @@ <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"شريحة SIM مؤمّنة."</string> <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"شريحة SIM مؤمّنة بكود PUK."</string> <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"جارٍ إلغاء تأمين شريحة SIM…"</string> - <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"إلغاء القفل باستخدام النقش."</string> - <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"إلغاء القفل باستخدام رمز PIN."</string> - <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"إلغاء القفل باستخدام كلمة المرور."</string> - <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"منطقة النقش."</string> - <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"منطقة التمرير."</string> <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"منطقة رقم التعريف الشخصي"</string> <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"منطقة رقم التعريف الشخصي لبطاقة SIM"</string> <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"منطقة PUK لبطاقة SIM"</string> diff --git a/packages/Keyguard/res/values-az-rAZ/strings.xml b/packages/Keyguard/res/values-az-rAZ/strings.xml index a8a115534b79..c7a80919c670 100644 --- a/packages/Keyguard/res/values-az-rAZ/strings.xml +++ b/packages/Keyguard/res/values-az-rAZ/strings.xml @@ -46,11 +46,6 @@ <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM kart kilidlənib."</string> <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SİM kart PUK ilə kilidlənib."</string> <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"SİM kartın kilidi açılır..."</string> - <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Kild açma modeli."</string> - <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Pin kilid açması."</string> - <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Şifrə kilidi."</string> - <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Model sahəsi."</string> - <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Sürüşdürmə sahəsi."</string> <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"PIN sahəsi"</string> <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"SIM PIN sahəsi"</string> <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"SIM PUK sahəsi"</string> diff --git a/packages/Keyguard/res/values-b+sr+Latn/strings.xml b/packages/Keyguard/res/values-b+sr+Latn/strings.xml index 22dc0596998c..570f4bc96f86 100644 --- a/packages/Keyguard/res/values-b+sr+Latn/strings.xml +++ b/packages/Keyguard/res/values-b+sr+Latn/strings.xml @@ -46,11 +46,6 @@ <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM kartica je zaključana."</string> <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM kartica je zaključana PUK kodom."</string> <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"Otključavanje SIM kartice…"</string> - <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Otključavanje šablonom."</string> - <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Otključavanje PIN-om."</string> - <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Otključavanje lozinkom."</string> - <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Oblast šablona."</string> - <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Oblast prevlačenja."</string> <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"Oblast za PIN"</string> <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"Oblast za PIN za SIM"</string> <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"Oblast za PUK za SIM"</string> diff --git a/packages/Keyguard/res/values-be-rBY/strings.xml b/packages/Keyguard/res/values-be-rBY/strings.xml index ca6a4764406d..f357961a3b8b 100644 --- a/packages/Keyguard/res/values-be-rBY/strings.xml +++ b/packages/Keyguard/res/values-be-rBY/strings.xml @@ -46,11 +46,6 @@ <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM-карта заблакiраваная."</string> <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM-карта заблакiравана PUK-кодам."</string> <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"Разблакiраванне SIM-карты..."</string> - <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Узор разблакiроўкі."</string> - <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"PIN-код разблакiроўкі."</string> - <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Пароль разблакiроўкі."</string> - <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Вобласць узора."</string> - <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Вобласць слайда."</string> <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"Поле для PIN-кода"</string> <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"Поле для PIN-кода SIM-карты"</string> <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"Поле для PUK-кода SIM-карты"</string> diff --git a/packages/Keyguard/res/values-bg/strings.xml b/packages/Keyguard/res/values-bg/strings.xml index 7eb2dbdf0532..988e97f6b482 100644 --- a/packages/Keyguard/res/values-bg/strings.xml +++ b/packages/Keyguard/res/values-bg/strings.xml @@ -46,11 +46,6 @@ <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM картата е заключена."</string> <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM картата е заключена с PUK код."</string> <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"SIM картата се отключва…"</string> - <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Отключване с фигура."</string> - <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Отключване с ПИН код."</string> - <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Отключване с парола."</string> - <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Област на фигурата."</string> - <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Област на плъзгане."</string> <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"Област за ПИН кода"</string> <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"Област за ПИН кода на SIM картата"</string> <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"Област за PUK кода на SIM картата"</string> diff --git a/packages/Keyguard/res/values-bn-rBD/strings.xml b/packages/Keyguard/res/values-bn-rBD/strings.xml index 7a33e2101cf1..1a2a8dde99c1 100644 --- a/packages/Keyguard/res/values-bn-rBD/strings.xml +++ b/packages/Keyguard/res/values-bn-rBD/strings.xml @@ -46,11 +46,6 @@ <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"সিম কার্ড লক করা আছে৷"</string> <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"সিম কার্ডটি PUK কোড দিয়ে লক করা আছে৷"</string> <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"সিম কার্ড আনলক করা হচ্ছে…"</string> - <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"প্যাটার্ন দিয়ে আনলক৷"</string> - <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"পিন দিয়ে আনলক৷"</string> - <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"পাসওয়ার্ড দিয়ে আনলক৷"</string> - <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"প্যাটার্ন এলাকা৷"</string> - <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"স্লাইড করার এলাকা৷"</string> <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"পিন অঞ্চল"</string> <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"SIM পিন অঞ্চল"</string> <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"SIM PUK অঞ্চল"</string> diff --git a/packages/Keyguard/res/values-bs-rBA/strings.xml b/packages/Keyguard/res/values-bs-rBA/strings.xml index 3c3af7be86b5..b8ff2a9835db 100644 --- a/packages/Keyguard/res/values-bs-rBA/strings.xml +++ b/packages/Keyguard/res/values-bs-rBA/strings.xml @@ -46,11 +46,6 @@ <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM kartica je zaključana."</string> <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM kartica je zaključana PUK kodom."</string> <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"Otključavanje SIM kartice…"</string> - <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Otključavanje uzorkom."</string> - <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Otključavanje pinom."</string> - <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Otključavanje lozinkom."</string> - <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Uzorak oblasti."</string> - <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Oblast za pomjeranje klizača."</string> <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"Prostor za PIN"</string> <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"Prostor za SIM PIN"</string> <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"Prostor za SIM PUK"</string> diff --git a/packages/Keyguard/res/values-ca/strings.xml b/packages/Keyguard/res/values-ca/strings.xml index b542866e6df6..9207e0e201fe 100644 --- a/packages/Keyguard/res/values-ca/strings.xml +++ b/packages/Keyguard/res/values-ca/strings.xml @@ -46,11 +46,6 @@ <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"La targeta SIM està bloquejada."</string> <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"La targeta SIM està bloquejada pel PUK."</string> <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"S\'està desbloquejant la targeta SIM..."</string> - <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Desbloqueig mitjançant patró"</string> - <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Desbloqueig mitjançant PIN"</string> - <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Desbloqueig mitjançant contrasenya"</string> - <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Àrea de patró"</string> - <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Àrea per lliscar el dit"</string> <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"Zona del PIN"</string> <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"Zona del PIN de la SIM"</string> <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"Zona del PUK de la SIM"</string> diff --git a/packages/Keyguard/res/values-cs/strings.xml b/packages/Keyguard/res/values-cs/strings.xml index b3103239f654..aa7115dede28 100644 --- a/packages/Keyguard/res/values-cs/strings.xml +++ b/packages/Keyguard/res/values-cs/strings.xml @@ -46,11 +46,6 @@ <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM karta je zablokována."</string> <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM karta je zablokována pomocí kódu PUK."</string> <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"Odblokování SIM karty…"</string> - <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Odemknutí gestem."</string> - <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Odemknutí kódem PIN."</string> - <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Odemknutí heslem."</string> - <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Oblast pro zadání bezpečnostního gesta."</string> - <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Oblast pro přejetí prstem."</string> <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"Oblast kódu PIN"</string> <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"Oblast kódu PIN SIM karty"</string> <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"Oblast kódu PUK SIM karty"</string> diff --git a/packages/Keyguard/res/values-da/strings.xml b/packages/Keyguard/res/values-da/strings.xml index b46b536fffe9..ebea6eeb1989 100644 --- a/packages/Keyguard/res/values-da/strings.xml +++ b/packages/Keyguard/res/values-da/strings.xml @@ -46,11 +46,6 @@ <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM-kortet er låst."</string> <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM-kort er låst med PUK-koden."</string> <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"SIM-kortet låses op…"</string> - <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Lås op med mønster."</string> - <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Lås op med pinkode."</string> - <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Lås op med adgangskode."</string> - <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Mønsterområde."</string> - <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Strygeområde."</string> <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"Område for pinkoden"</string> <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"Område for pinkoden til simkortet"</string> <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"Område for PUK-koden til simkortet"</string> diff --git a/packages/Keyguard/res/values-de/strings.xml b/packages/Keyguard/res/values-de/strings.xml index ae731c343909..a519ce84b862 100644 --- a/packages/Keyguard/res/values-de/strings.xml +++ b/packages/Keyguard/res/values-de/strings.xml @@ -46,11 +46,6 @@ <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM-Karte ist gesperrt."</string> <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM-Karte ist gesperrt. PUK-Eingabe erforderlich."</string> <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"SIM-Karte wird entsperrt…"</string> - <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Entsperrung mit Muster"</string> - <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Entsperrung mit PIN"</string> - <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Entsperrung mit Passwort"</string> - <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Bereich für Muster"</string> - <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Bereich für Fingerbewegung"</string> <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"PIN-Bereich"</string> <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"SIM-PIN-Bereich"</string> <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"SIM-PUK-Bereich"</string> diff --git a/packages/Keyguard/res/values-el/strings.xml b/packages/Keyguard/res/values-el/strings.xml index c54a7fc87aa4..d9692667ba0f 100644 --- a/packages/Keyguard/res/values-el/strings.xml +++ b/packages/Keyguard/res/values-el/strings.xml @@ -46,11 +46,6 @@ <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"Η κάρτα SIM είναι κλειδωμένη."</string> <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"Η κάρτα SIM είναι κλειδωμένη με κωδικό PUK."</string> <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"Ξεκλείδωμα κάρτας SIM…"</string> - <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Ξεκλείδωμα μοτίβου."</string> - <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Ξεκλείδωμα κωδικού ασφαλείας"</string> - <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Ξεκλείδωμα κωδικού πρόσβασης."</string> - <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Περιοχή μοτίβου."</string> - <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Περιοχή ολίσθησης"</string> <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"Περιοχή PIN"</string> <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"Περιοχή PIN SIM"</string> <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"Περιοχή PUK SIM"</string> diff --git a/packages/Keyguard/res/values-en-rAU/strings.xml b/packages/Keyguard/res/values-en-rAU/strings.xml index e88516679f45..9ecd979163f2 100644 --- a/packages/Keyguard/res/values-en-rAU/strings.xml +++ b/packages/Keyguard/res/values-en-rAU/strings.xml @@ -46,11 +46,6 @@ <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM card is locked."</string> <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM card is PUK-locked."</string> <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"Unlocking SIM card…"</string> - <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Pattern unlock."</string> - <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Pin unlock."</string> - <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Password unlock."</string> - <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Pattern area."</string> - <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Slide area."</string> <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"PIN area"</string> <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"SIM PIN area"</string> <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"SIM PUK area"</string> diff --git a/packages/Keyguard/res/values-en-rGB/strings.xml b/packages/Keyguard/res/values-en-rGB/strings.xml index e88516679f45..9ecd979163f2 100644 --- a/packages/Keyguard/res/values-en-rGB/strings.xml +++ b/packages/Keyguard/res/values-en-rGB/strings.xml @@ -46,11 +46,6 @@ <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM card is locked."</string> <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM card is PUK-locked."</string> <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"Unlocking SIM card…"</string> - <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Pattern unlock."</string> - <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Pin unlock."</string> - <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Password unlock."</string> - <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Pattern area."</string> - <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Slide area."</string> <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"PIN area"</string> <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"SIM PIN area"</string> <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"SIM PUK area"</string> diff --git a/packages/Keyguard/res/values-en-rIN/strings.xml b/packages/Keyguard/res/values-en-rIN/strings.xml index e88516679f45..9ecd979163f2 100644 --- a/packages/Keyguard/res/values-en-rIN/strings.xml +++ b/packages/Keyguard/res/values-en-rIN/strings.xml @@ -46,11 +46,6 @@ <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM card is locked."</string> <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM card is PUK-locked."</string> <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"Unlocking SIM card…"</string> - <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Pattern unlock."</string> - <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Pin unlock."</string> - <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Password unlock."</string> - <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Pattern area."</string> - <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Slide area."</string> <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"PIN area"</string> <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"SIM PIN area"</string> <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"SIM PUK area"</string> diff --git a/packages/Keyguard/res/values-es-rUS/strings.xml b/packages/Keyguard/res/values-es-rUS/strings.xml index df0db2d32d4c..61f5c0d538b6 100644 --- a/packages/Keyguard/res/values-es-rUS/strings.xml +++ b/packages/Keyguard/res/values-es-rUS/strings.xml @@ -46,11 +46,6 @@ <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"La tarjeta SIM está bloqueada."</string> <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"La tarjeta SIM está bloqueada por código PUK."</string> <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"Desbloqueando tarjeta SIM…"</string> - <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Desbloqueo por patrón"</string> - <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Desbloqueo por PIN"</string> - <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Desbloqueo por contraseña"</string> - <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Área de patrón"</string> - <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Área de deslizamiento"</string> <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"Área de PIN"</string> <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"Área de PIN de SIM"</string> <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"Área de PUK de SIM"</string> diff --git a/packages/Keyguard/res/values-es/strings.xml b/packages/Keyguard/res/values-es/strings.xml index 6061b784378f..3ef737c22764 100644 --- a/packages/Keyguard/res/values-es/strings.xml +++ b/packages/Keyguard/res/values-es/strings.xml @@ -46,11 +46,6 @@ <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"La tarjeta SIM está bloqueada."</string> <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"La tarjeta SIM está bloqueada con el código PUK."</string> <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"Desbloqueando tarjeta SIM…"</string> - <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Desbloqueo por patrón"</string> - <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Desbloqueo por PIN"</string> - <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Desbloqueo por contraseña"</string> - <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Área de patrón"</string> - <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Área para deslizar"</string> <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"Área de PIN"</string> <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"Área de PIN de SIM"</string> <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"Área de PUK de SIM"</string> diff --git a/packages/Keyguard/res/values-et-rEE/strings.xml b/packages/Keyguard/res/values-et-rEE/strings.xml index 78ae3cacaea5..47b6332c92c2 100644 --- a/packages/Keyguard/res/values-et-rEE/strings.xml +++ b/packages/Keyguard/res/values-et-rEE/strings.xml @@ -46,11 +46,6 @@ <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM-kaart on lukus."</string> <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM-kaart on PUK-lukus."</string> <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"SIM-kaardi avamine ..."</string> - <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Mustriga avamine."</string> - <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"PIN-koodiga avamine."</string> - <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Parooliga avamine."</string> - <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Mustri ala."</string> - <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Lohistamisala."</string> <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"PIN-koodi ala"</string> <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"SIM-kaardi PIN-koodi ala"</string> <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"SIM-kaardi PUK-koodi ala"</string> diff --git a/packages/Keyguard/res/values-eu-rES/strings.xml b/packages/Keyguard/res/values-eu-rES/strings.xml index 7855b16e82b9..5f4abce03f1b 100644 --- a/packages/Keyguard/res/values-eu-rES/strings.xml +++ b/packages/Keyguard/res/values-eu-rES/strings.xml @@ -46,11 +46,6 @@ <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM txartela blokeatuta dago."</string> <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM txartela PUK bidez blokeatuta dago."</string> <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"SIM txartela desblokeatzen…"</string> - <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Ereduaren bidez desblokeatzea."</string> - <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"PIN kodearen bidez desblokeatzea."</string> - <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Pasahitzaren bidez desblokeatzea."</string> - <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Eredua marrazteko eremua."</string> - <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Hatza lerratzeko eremua."</string> <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"PIN kodearen eremua"</string> <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"SIM txartelaren PIN kodearen eremua"</string> <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"SIM txartelaren PUK kodearen eremua"</string> diff --git a/packages/Keyguard/res/values-fa/strings.xml b/packages/Keyguard/res/values-fa/strings.xml index 39fd4608de51..40952e256a5f 100644 --- a/packages/Keyguard/res/values-fa/strings.xml +++ b/packages/Keyguard/res/values-fa/strings.xml @@ -46,11 +46,6 @@ <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"سیم کارت قفل شد."</string> <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"سیم کارت با PUK قفل شده است."</string> <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"درحال بازگشایی قفل سیم کارت..."</string> - <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"باز کردن قفل با الگو."</string> - <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"باز کردن قفل با پین."</string> - <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"باز کردن قفل با گذرواژه."</string> - <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"ناحیه الگو."</string> - <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"ناحیه کشیدن انگشت روی صفحه."</string> <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"قسمت پین"</string> <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"قسمت پین سیمکارت"</string> <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"قسمت PUK سیمکارت"</string> diff --git a/packages/Keyguard/res/values-fi/strings.xml b/packages/Keyguard/res/values-fi/strings.xml index 7a0c00f83bf7..a1b96ca2f671 100644 --- a/packages/Keyguard/res/values-fi/strings.xml +++ b/packages/Keyguard/res/values-fi/strings.xml @@ -46,11 +46,6 @@ <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM-kortti on lukittu."</string> <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM-kortti on PUK-lukittu."</string> <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"SIM-kortin lukitusta poistetaan…"</string> - <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Lukituksen poisto salasanalla."</string> - <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Lukituksen poisto PIN-koodilla."</string> - <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Lukituksen poisto salasanalla."</string> - <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Kuvioalue."</string> - <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Liu\'utusalue."</string> <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"PIN-koodin alue"</string> <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"SIM-kortin PIN-koodin alue"</string> <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"SIM-kortin PUK-koodin alue"</string> diff --git a/packages/Keyguard/res/values-fr-rCA/strings.xml b/packages/Keyguard/res/values-fr-rCA/strings.xml index 9bc2456809d6..d920415a69cc 100644 --- a/packages/Keyguard/res/values-fr-rCA/strings.xml +++ b/packages/Keyguard/res/values-fr-rCA/strings.xml @@ -46,11 +46,6 @@ <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"La carte SIM est verrouillée."</string> <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"La carte SIM est verrouillée par clé PUK."</string> <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"Déverrouillage de la carte SIM en cours…"</string> - <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Déverrouillage par schéma"</string> - <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Déverrouillage par NIP"</string> - <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Déverrouillage par mot de passe"</string> - <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Zone du schéma"</string> - <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Zone où faire glisser votre doigt sur l\'écran"</string> <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"Zone du NIP"</string> <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"Zone du NIP de la carte SIM"</string> <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"Zone du code PUK de la carte SIM"</string> diff --git a/packages/Keyguard/res/values-fr/strings.xml b/packages/Keyguard/res/values-fr/strings.xml index ecb2575d2e9a..8615b99df2bf 100644 --- a/packages/Keyguard/res/values-fr/strings.xml +++ b/packages/Keyguard/res/values-fr/strings.xml @@ -46,11 +46,6 @@ <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"La carte SIM est verrouillée."</string> <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"La carte SIM est verrouillée par clé PUK."</string> <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"Déverrouillage de la carte SIM en cours…"</string> - <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Déverrouillage par schéma"</string> - <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Déverrouillage par code PIN"</string> - <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Déverrouillage par mot de passe"</string> - <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Zone du schéma"</string> - <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Zone où faire glisser votre doigt sur l\'écran"</string> <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"Champ du code PIN"</string> <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"Champ du code PIN de la carte SIM"</string> <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"Champ du code PUK de la carte SIM"</string> diff --git a/packages/Keyguard/res/values-gl-rES/strings.xml b/packages/Keyguard/res/values-gl-rES/strings.xml index 382dd7bf3e13..a894fc5b9ccd 100644 --- a/packages/Keyguard/res/values-gl-rES/strings.xml +++ b/packages/Keyguard/res/values-gl-rES/strings.xml @@ -46,11 +46,6 @@ <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"A tarxeta SIM está bloqueada."</string> <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"A tarxeta SIM está bloqueada mediante un PUK."</string> <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"Desbloqueando tarxeta SIM…"</string> - <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Desbloqueo mediante padrón"</string> - <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Desbloqueo mediante PIN"</string> - <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Desbloqueo mediante contrasinal"</string> - <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Zona do padrón"</string> - <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Zona para pasar o dedo"</string> <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"Área do PIN"</string> <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"Área do PIN da tarxeta SIM"</string> <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"Área do PUK da tarxeta SIM"</string> diff --git a/packages/Keyguard/res/values-gu-rIN/strings.xml b/packages/Keyguard/res/values-gu-rIN/strings.xml index eddd1a158486..d288b3f9da78 100644 --- a/packages/Keyguard/res/values-gu-rIN/strings.xml +++ b/packages/Keyguard/res/values-gu-rIN/strings.xml @@ -46,11 +46,6 @@ <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM કાર્ડ લૉક કરેલ છે."</string> <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM કાર્ડ, PUK-લૉક કરેલ છે."</string> <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"SIM કાર્ડ અનલૉક કરી રહ્યાં છે…"</string> - <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"પેટર્ન અનલૉક."</string> - <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"પિન અનલૉક."</string> - <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"પાસવર્ડ અનલૉક કરો."</string> - <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"પેટર્ન ક્ષેત્ર."</string> - <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"સ્લાઇડ ક્ષેત્ર."</string> <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"PIN ક્ષેત્ર"</string> <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"SIM PIN ક્ષેત્ર"</string> <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"SIM PUK ક્ષેત્ર"</string> diff --git a/packages/Keyguard/res/values-hi/strings.xml b/packages/Keyguard/res/values-hi/strings.xml index 8069c5e9c464..bf36312870e5 100644 --- a/packages/Keyguard/res/values-hi/strings.xml +++ b/packages/Keyguard/res/values-hi/strings.xml @@ -46,11 +46,6 @@ <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"सिम कार्ड लॉक है."</string> <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"सिम कार्ड PUK द्वारा लॉक किया हुआ है."</string> <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"सिम कार्ड अनलॉक हो रहा है…"</string> - <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"आकार अनलॉक."</string> - <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"पिन अनलॉक."</string> - <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"पासवर्ड अनलॉक."</string> - <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"आकार क्षेत्र."</string> - <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"स्लाइड क्षेत्र."</string> <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"पिन क्षेत्र"</string> <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"सिम पिन क्षेत्र"</string> <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"सिम पिइउके क्षेत्र"</string> diff --git a/packages/Keyguard/res/values-hr/strings.xml b/packages/Keyguard/res/values-hr/strings.xml index 044786d6297d..169bc5716bbb 100644 --- a/packages/Keyguard/res/values-hr/strings.xml +++ b/packages/Keyguard/res/values-hr/strings.xml @@ -46,11 +46,6 @@ <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM kartica je zaključana."</string> <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM kartica zaključana je PUK-om."</string> <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"Otključavanje SIM kartice…"</string> - <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Uzorak za otključavanje."</string> - <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Otključavanje PIN-om."</string> - <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Otključavanje zaporkom."</string> - <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Područje uzorka."</string> - <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Područje klizanja."</string> <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"Područje PIN-a"</string> <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"Područje PIN-a za SIM"</string> <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"Područje PUK-a za SIM"</string> diff --git a/packages/Keyguard/res/values-hu/strings.xml b/packages/Keyguard/res/values-hu/strings.xml index e54a89f42fa6..bc3bf4e0427f 100644 --- a/packages/Keyguard/res/values-hu/strings.xml +++ b/packages/Keyguard/res/values-hu/strings.xml @@ -46,11 +46,6 @@ <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"A SIM kártya le van zárva."</string> <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"A SIM kártya le van zárva a PUK kóddal."</string> <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"SIM kártya feloldása..."</string> - <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Feloldás mintával"</string> - <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Feloldás PIN kóddal"</string> - <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Feloldás jelszóval"</string> - <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Mintaterület"</string> - <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Csúsztatási terület"</string> <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"PIN-kód területe"</string> <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"SIM PIN-kód területe"</string> <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"SIM PUK kód területe"</string> diff --git a/packages/Keyguard/res/values-hy-rAM/strings.xml b/packages/Keyguard/res/values-hy-rAM/strings.xml index 6758a2e962c4..4aacf8fb927a 100644 --- a/packages/Keyguard/res/values-hy-rAM/strings.xml +++ b/packages/Keyguard/res/values-hy-rAM/strings.xml @@ -46,11 +46,6 @@ <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM քարտը կողպված է:"</string> <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM քարտը PUK-ով կողպված է:"</string> <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"SIM քարտը ապակողպվում է..."</string> - <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Սխեմայով ապակողպում:"</string> - <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Pin-ն ապակողպված է:"</string> - <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Գաղտնաբառի ապակողպում:"</string> - <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Սխեմայի տարածք:"</string> - <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Սահեցման տարածք:"</string> <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"PIN կոդի տարածք"</string> <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"SIM քարտի PIN կոդի տարածք"</string> <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"SIM քարտի PUK կոդի տարածք"</string> diff --git a/packages/Keyguard/res/values-in/strings.xml b/packages/Keyguard/res/values-in/strings.xml index 6f8e7f1c6ddb..dda63a88568c 100644 --- a/packages/Keyguard/res/values-in/strings.xml +++ b/packages/Keyguard/res/values-in/strings.xml @@ -46,11 +46,6 @@ <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"Kartu SIM terkunci."</string> <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"Kartu SIM terkunci PUK."</string> <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"Membuka kartu SIM…"</string> - <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Buka kunci dengan pola."</string> - <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Buka kunci dengan PIN."</string> - <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Buka kunci dengan sandi."</string> - <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Area pola."</string> - <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Area geser."</string> <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"Bidang PIN"</string> <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"Bidang PIN SIM"</string> <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"Bidang PUK SIM"</string> diff --git a/packages/Keyguard/res/values-is-rIS/strings.xml b/packages/Keyguard/res/values-is-rIS/strings.xml index 279ffcfb51b4..278e03113673 100644 --- a/packages/Keyguard/res/values-is-rIS/strings.xml +++ b/packages/Keyguard/res/values-is-rIS/strings.xml @@ -46,11 +46,6 @@ <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM-kortið er læst."</string> <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM-kortið er PUK-læst."</string> <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"Tekur SIM-kort úr lás…"</string> - <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Opnun með mynstri."</string> - <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Opnun með PIN-númeri."</string> - <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Opnun með aðgangsorði."</string> - <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Svæði mynsturs."</string> - <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Stroksvæði."</string> <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"PIN-svæði"</string> <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"PIN-svæði SIM-korts"</string> <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"PUK-svæði SIM-korts"</string> diff --git a/packages/Keyguard/res/values-it/strings.xml b/packages/Keyguard/res/values-it/strings.xml index 728974df96bc..98bcae4775b9 100644 --- a/packages/Keyguard/res/values-it/strings.xml +++ b/packages/Keyguard/res/values-it/strings.xml @@ -46,11 +46,6 @@ <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"La SIM è bloccata."</string> <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"La SIM è bloccata tramite PUK."</string> <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"Sblocco scheda SIM..."</string> - <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Sblocco con sequenza."</string> - <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Sblocco con PIN."</string> - <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Sblocco con password."</string> - <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Area sequenza."</string> - <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Area di scorrimento."</string> <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"Area PIN"</string> <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"Area PIN SIM"</string> <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"Area PUK SIM"</string> diff --git a/packages/Keyguard/res/values-iw/strings.xml b/packages/Keyguard/res/values-iw/strings.xml index 47d0728af3ff..8d1ada3a342a 100644 --- a/packages/Keyguard/res/values-iw/strings.xml +++ b/packages/Keyguard/res/values-iw/strings.xml @@ -46,11 +46,6 @@ <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"כרטיס ה-SIM נעול."</string> <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"כרטיס SIM נעול באמצעות PUK."</string> <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"מבטל נעילה של כרטיס SIM…"</string> - <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"ביטול נעילה באמצעות ציור קו."</string> - <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"ביטול נעילה באמצעות מספר PIN."</string> - <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"ביטול נעילה באמצעות סיסמה."</string> - <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"אזור ציור קו."</string> - <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"אזור הסטה."</string> <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"אזור עבור קוד PIN"</string> <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"אזור עבור קוד PIN של SIM"</string> <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"אזור עבור קוד PUK של SIM"</string> diff --git a/packages/Keyguard/res/values-ja/strings.xml b/packages/Keyguard/res/values-ja/strings.xml index d30355fedce8..c4b4c9856487 100644 --- a/packages/Keyguard/res/values-ja/strings.xml +++ b/packages/Keyguard/res/values-ja/strings.xml @@ -46,11 +46,6 @@ <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIMカードはロックされています。"</string> <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIMカードはPUKでロックされています。"</string> <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"SIMカードをロック解除しています…"</string> - <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"パターンロックを解除します。"</string> - <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"PINロックを解除します。"</string> - <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"パスワードロックを解除します。"</string> - <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"パターンエリアです。"</string> - <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"スライドエリアです。"</string> <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"PINエリア"</string> <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"SIM PINエリア"</string> <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"SIM PUKエリア"</string> diff --git a/packages/Keyguard/res/values-ka-rGE/strings.xml b/packages/Keyguard/res/values-ka-rGE/strings.xml index a398e00838ec..658194ff0c4a 100644 --- a/packages/Keyguard/res/values-ka-rGE/strings.xml +++ b/packages/Keyguard/res/values-ka-rGE/strings.xml @@ -46,11 +46,6 @@ <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM ბარათი დაბლოკილია."</string> <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM ბარათი დაბლოკილია PUK კოდით."</string> <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"მიმდინარეობს SIM ბარათის განბლოკვა…"</string> - <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"განბლოკვა ნიმუშით."</string> - <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"განბლოკვა Pin-ით."</string> - <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"პაროლის განბლოკვა"</string> - <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"ნიმუშების სივრცე."</string> - <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"გადასრიალების სივრცე."</string> <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"PIN-ის არე"</string> <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"SIM-ის PIN-ის არე"</string> <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"SIM-ის PUK-ის არე"</string> diff --git a/packages/Keyguard/res/values-kk-rKZ/strings.xml b/packages/Keyguard/res/values-kk-rKZ/strings.xml index be261fb332ab..2eb3948778af 100644 --- a/packages/Keyguard/res/values-kk-rKZ/strings.xml +++ b/packages/Keyguard/res/values-kk-rKZ/strings.xml @@ -46,11 +46,6 @@ <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM картасы бекітулі."</string> <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM картасының PUK коды бекітілген."</string> <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"SIM картасының бекітпесін ашуда…"</string> - <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Кескін арқылы ашу."</string> - <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Pin арқылы ашу."</string> - <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Құпия сөз арқылы ашу."</string> - <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Кескін арқылы ашу аймағы."</string> - <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Сырғыту аймағы."</string> <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"PIN аумағы"</string> <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"SIM PIN аумағы"</string> <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"SIM PUK аумағы"</string> diff --git a/packages/Keyguard/res/values-km-rKH/strings.xml b/packages/Keyguard/res/values-km-rKH/strings.xml index 4d3f6e86efbe..fce46c732a5a 100644 --- a/packages/Keyguard/res/values-km-rKH/strings.xml +++ b/packages/Keyguard/res/values-km-rKH/strings.xml @@ -46,11 +46,6 @@ <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"ស៊ីមកាតជាប់សោ។"</string> <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"ស៊ីមកាតជាប់កូដ PUK ។"</string> <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"កំពុងដោះសោស៊ីមកាត..."</string> - <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"លំនាំដោះសោ។"</string> - <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"កូដ PIN ដោះសោ។"</string> - <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"ពាក្យសម្ងាត់ដោះសោ។"</string> - <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"ផ្ទៃលំនាំ។"</string> - <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"ផ្ទៃរុញ។"</string> <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"ប្រអប់លេខសម្ងាត់"</string> <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"ប្រអប់លេខសម្ងាត់ស៊ីម"</string> <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"ប្រអប់ PUK ស៊ីម"</string> diff --git a/packages/Keyguard/res/values-kn-rIN/strings.xml b/packages/Keyguard/res/values-kn-rIN/strings.xml index 5691a6354b22..7bac9c6c4c1b 100644 --- a/packages/Keyguard/res/values-kn-rIN/strings.xml +++ b/packages/Keyguard/res/values-kn-rIN/strings.xml @@ -46,11 +46,6 @@ <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"ಸಿಮ್ ಕಾರ್ಡ್ ಲಾಕ್ ಮಾಡಲಾಗಿದೆ."</string> <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"ಸಿಮ್ ಕಾರ್ಡ್ ಅನ್ನು PUK-ಲಾಕ್ ಮಾಡಲಾಗಿದೆ."</string> <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"ಸಿಮ್ ಕಾರ್ಡ್ ಅನ್ಲಾಕ್ ಮಾಡಲಾಗುತ್ತಿದೆ…"</string> - <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"ಪ್ಯಾಟರ್ನ್ ಅನ್ಲಾಕ್."</string> - <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"ಪಿನ್ ಅನ್ಲಾಕ್."</string> - <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"ಪಾಸ್ವರ್ಡ್ ಅನ್ಲಾಕ್."</string> - <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"ಪ್ಯಾಟರ್ನ್ ಪ್ರದೇಶ."</string> - <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"ಸ್ಲೈಡ್ ಪ್ರದೇಶ."</string> <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"ಪಿನ್ ಪ್ರದೇಶ"</string> <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"ಸಿಮ್ ಪಿನ್ ಪ್ರದೇಶ"</string> <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"ಸಿಮ್ PUK ಪ್ರದೇಶ"</string> diff --git a/packages/Keyguard/res/values-ko/strings.xml b/packages/Keyguard/res/values-ko/strings.xml index 2eeef2b40220..5d40d4d2a954 100644 --- a/packages/Keyguard/res/values-ko/strings.xml +++ b/packages/Keyguard/res/values-ko/strings.xml @@ -46,11 +46,6 @@ <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM 카드가 잠겨 있습니다."</string> <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM 카드가 PUK 잠김 상태입니다."</string> <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"SIM 카드 잠금해제 중..."</string> - <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"패턴을 사용하여 잠금해제합니다."</string> - <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"핀을 사용하여 잠금해제합니다."</string> - <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"비밀번호를 사용하여 잠금해제합니다."</string> - <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"패턴을 그리는 부분입니다."</string> - <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"슬라이드하는 부분입니다."</string> <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"PIN 영역"</string> <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"SIM PIN 영역"</string> <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"SIM PUK 영역"</string> diff --git a/packages/Keyguard/res/values-ky-rKG/strings.xml b/packages/Keyguard/res/values-ky-rKG/strings.xml index d42b1fab3a01..a48552844ffe 100644 --- a/packages/Keyguard/res/values-ky-rKG/strings.xml +++ b/packages/Keyguard/res/values-ky-rKG/strings.xml @@ -46,11 +46,6 @@ <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM-карта бөгөттөлгөн."</string> <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM-карта PUK-бөгөттө."</string> <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"SIM-карта бөгөттөн чыгарылууда…"</string> - <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Үлгү менен ачуу."</string> - <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Пин код менен ачуу."</string> - <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Сырсөз менен ачуу."</string> - <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Үлгү аймагы."</string> - <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Жылмыштыруу аймагы."</string> <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"PIN аймагы"</string> <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"SIM PIN аймагы"</string> <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"SIM PUK аймагы"</string> diff --git a/packages/Keyguard/res/values-lo-rLA/strings.xml b/packages/Keyguard/res/values-lo-rLA/strings.xml index 8e7c8136c6ca..29a1b562cf20 100644 --- a/packages/Keyguard/res/values-lo-rLA/strings.xml +++ b/packages/Keyguard/res/values-lo-rLA/strings.xml @@ -46,11 +46,6 @@ <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"ຊິມກາດຖືກລັອກ."</string> <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"ຊິມກາດຖືກລັອກດ້ວຍລະຫັດ PUK."</string> <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"ກຳລັງປົດລັອກຊິມກາດ..."</string> - <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"ປົດລັອກດ້ວຍຮູບແບບ."</string> - <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"ປົດລັອກດ້ວຍ PIN."</string> - <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"ການປົດລັອກດ້ວຍລະຫັດຜ່ານ."</string> - <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"ພື້ນທີ່ຮູບແບບ."</string> - <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"ເລື່ອນພື້ນທີ່."</string> <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"ພື້ນທີ່ PIN"</string> <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"ພື້ນທີ່ PIN ຂອງ SIM"</string> <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"ພື້ນທີ່ PUK ຂອງ SIM"</string> diff --git a/packages/Keyguard/res/values-lt/strings.xml b/packages/Keyguard/res/values-lt/strings.xml index 653c089b915b..fd41efc28db3 100644 --- a/packages/Keyguard/res/values-lt/strings.xml +++ b/packages/Keyguard/res/values-lt/strings.xml @@ -46,11 +46,6 @@ <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM kortelė užrakinta."</string> <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM kortelė užrakinta PUK kodu."</string> <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"Atrakinama SIM kortelė…"</string> - <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Atrakinimas pagal piešinį."</string> - <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Atrakinimas įvedus PIN kodą."</string> - <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Atrakinimas įvedus slaptažodį."</string> - <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Atrakinimo pagal piešinį sritis."</string> - <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Slydimo sritis."</string> <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"PIN kodo sritis"</string> <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"SIM kortelės PIN kodo sritis"</string> <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"SIM kortelės PUK kodo sritis"</string> diff --git a/packages/Keyguard/res/values-lv/strings.xml b/packages/Keyguard/res/values-lv/strings.xml index 449659e9e63c..f801d649fa0a 100644 --- a/packages/Keyguard/res/values-lv/strings.xml +++ b/packages/Keyguard/res/values-lv/strings.xml @@ -46,11 +46,6 @@ <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM karte ir bloķēta."</string> <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM karte ir bloķēta ar PUK."</string> <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"Notiek SIM kartes atbloķēšana..."</string> - <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Autorizācija ar kombināciju."</string> - <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Autorizācija ar PIN kodu."</string> - <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Autorizācija ar paroli."</string> - <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Kombinācijas ievades apgabals."</string> - <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Apgabals, kur vilkt ar pirkstu."</string> <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"PIN apgabals"</string> <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"SIM PIN apgabals"</string> <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"SIM PUK apgabals"</string> diff --git a/packages/Keyguard/res/values-mk-rMK/strings.xml b/packages/Keyguard/res/values-mk-rMK/strings.xml index a6ee92106768..9d833f0266f2 100644 --- a/packages/Keyguard/res/values-mk-rMK/strings.xml +++ b/packages/Keyguard/res/values-mk-rMK/strings.xml @@ -46,11 +46,6 @@ <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"СИМ картичката е заклучена."</string> <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"СИМ картичката е заклучена со ПУК."</string> <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"СИМ картичката се отклучува..."</string> - <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Отклучување со шема."</string> - <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Отклучување со пин."</string> - <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Отклучување со лозинка."</string> - <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Област за шема."</string> - <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Област за лизгање."</string> <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"Поле за PIN"</string> <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"Поле за PIN на СИМ"</string> <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"Поле за ПУК на СИМ"</string> diff --git a/packages/Keyguard/res/values-ml-rIN/strings.xml b/packages/Keyguard/res/values-ml-rIN/strings.xml index fa39ae11af9b..5d93cf003878 100644 --- a/packages/Keyguard/res/values-ml-rIN/strings.xml +++ b/packages/Keyguard/res/values-ml-rIN/strings.xml @@ -46,11 +46,6 @@ <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"സിം കാർഡ് ലോക്കുചെയ്തു."</string> <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"സിം കാർഡ് PUK-ലോക്ക് ചെയ്തതാണ്."</string> <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"സിം കാർഡ് അൺലോക്കുചെയ്യുന്നു…"</string> - <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"പാറ്റേൺ അൺലോക്ക്."</string> - <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"പിൻ അൺലോക്ക്."</string> - <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"പാസ്വേഡ് അൺലോക്ക്."</string> - <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"പാറ്റേൺ ഏരിയ."</string> - <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"സ്ലൈഡ് ഏരിയ."</string> <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"PIN ഏരിയ"</string> <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"SIM PIN ഏരിയ"</string> <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"SIM PUK ഏരിയ"</string> diff --git a/packages/Keyguard/res/values-mn-rMN/strings.xml b/packages/Keyguard/res/values-mn-rMN/strings.xml index fae032884c0b..8641e31285fb 100644 --- a/packages/Keyguard/res/values-mn-rMN/strings.xml +++ b/packages/Keyguard/res/values-mn-rMN/strings.xml @@ -46,11 +46,6 @@ <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM карт түгжигдсэн."</string> <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM картны PUK-түгжигдсэн."</string> <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"SIM картны түгжээг гаргаж байна…"</string> - <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Тайлах хээ."</string> - <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Тайлах пин."</string> - <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Тайлах нууц үг."</string> - <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Хээний хэсэг."</string> - <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Гулсуулах хэсэг."</string> <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"PIN талбар"</string> <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"SIM PIN талбар"</string> <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"SIM PUK талбар"</string> diff --git a/packages/Keyguard/res/values-mr-rIN/strings.xml b/packages/Keyguard/res/values-mr-rIN/strings.xml index 57a95be9971b..8bcaad6cc504 100644 --- a/packages/Keyguard/res/values-mr-rIN/strings.xml +++ b/packages/Keyguard/res/values-mr-rIN/strings.xml @@ -46,11 +46,6 @@ <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"सिम कार्ड लॉक झाले आहे."</string> <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"सिम कार्ड PUK-लॉक केलेले आहे."</string> <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"सिम कार्ड अनलॉक करत आहे…"</string> - <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"नमुना अनलॉक."</string> - <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"पिन अनलॉक."</string> - <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"संकेतशब्द अनलॉक."</string> - <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"नमुना क्षेत्र."</string> - <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"स्लाइड क्षेत्र."</string> <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"पिन क्षेत्र"</string> <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"सिम पिन क्षेत्र"</string> <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"सिम PUK क्षेत्र"</string> diff --git a/packages/Keyguard/res/values-ms-rMY/strings.xml b/packages/Keyguard/res/values-ms-rMY/strings.xml index 803d40a27133..b7b093f085bf 100644 --- a/packages/Keyguard/res/values-ms-rMY/strings.xml +++ b/packages/Keyguard/res/values-ms-rMY/strings.xml @@ -46,11 +46,6 @@ <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"Kad SIM dikunci."</string> <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"Kad SIM dikunci dengan PUK."</string> <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"Membuka kunci kad SIM..."</string> - <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Buka kunci corak."</string> - <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Buka kunci pin."</string> - <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Buka kunci kata laluan."</string> - <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Kawasan corak."</string> - <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Kawasan luncur."</string> <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"Kawasan PIN"</string> <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"Kawasan PIN SIM"</string> <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"Kawasan PUK SIM"</string> diff --git a/packages/Keyguard/res/values-my-rMM/strings.xml b/packages/Keyguard/res/values-my-rMM/strings.xml index fd800e4a50fc..7a7664e20287 100644 --- a/packages/Keyguard/res/values-my-rMM/strings.xml +++ b/packages/Keyguard/res/values-my-rMM/strings.xml @@ -46,11 +46,6 @@ <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"ဆင်းမ်ကဒ် သော့ကျနေပါသည်"</string> <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"ဆင်းမ်ကဒ် ရဲ့ ပင်နံပါတ် ပြန်ဖွင့်သည့် ကုဒ် သော့ကျနေပါသည်"</string> <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"ဆင်းမ်ကဒ် ကို သော့ဖွင့်နေပါသည်"</string> - <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"ပုံစံဖြင့် သော့ဖွင့်ခြင်း"</string> - <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"ပင်နံပါတ်ဖြင့် သော့ဖွင့်ခြင်း"</string> - <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"စကားဝှက်ဖြင့် သော့ဖွင့်ခြင်း"</string> - <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"ပုံစံနေရာ"</string> - <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"ဘေးတိုက်ပွတ်ဆွဲရန် နေရာ"</string> <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"PIN နေရာ"</string> <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"SIM PIN နေရာ"</string> <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"SIM PUK နေရာ"</string> diff --git a/packages/Keyguard/res/values-nb/strings.xml b/packages/Keyguard/res/values-nb/strings.xml index 1bdf444c05e8..e0035daa10ba 100644 --- a/packages/Keyguard/res/values-nb/strings.xml +++ b/packages/Keyguard/res/values-nb/strings.xml @@ -46,11 +46,6 @@ <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM-kortet er låst."</string> <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM-kortet er PUK-låst."</string> <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"Låser opp SIM-kortet ..."</string> - <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Mønsteropplåsning."</string> - <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"PIN-opplåsning."</string> - <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Passordopplåsning."</string> - <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Mønsterområde."</string> - <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Dra-felt."</string> <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"PIN-området"</string> <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"PIN-området for SIM-kortet"</string> <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"PUK-området for SIM-kortet"</string> diff --git a/packages/Keyguard/res/values-ne-rNP/strings.xml b/packages/Keyguard/res/values-ne-rNP/strings.xml index 2cf863d25a1c..47f5432a5447 100644 --- a/packages/Keyguard/res/values-ne-rNP/strings.xml +++ b/packages/Keyguard/res/values-ne-rNP/strings.xml @@ -46,11 +46,6 @@ <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM कार्ड लक गरियो।"</string> <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM कार्ड PUK-लक छ।"</string> <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"SIM कार्ड अनलक हुँदै…"</string> - <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"ढाँचा अनलक।"</string> - <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Pin अनलक"</string> - <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"पासवर्ड अनलक।"</string> - <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"ढाँचा क्षेत्र।"</string> - <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"स्लाइड क्षेत्र।"</string> <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"पीन क्षेत्र"</string> <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"SIM पिन क्षेत्र"</string> <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"SIM पुक क्षेत्र"</string> diff --git a/packages/Keyguard/res/values-nl/strings.xml b/packages/Keyguard/res/values-nl/strings.xml index a33165d8e781..c44381efc817 100644 --- a/packages/Keyguard/res/values-nl/strings.xml +++ b/packages/Keyguard/res/values-nl/strings.xml @@ -46,11 +46,6 @@ <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"Simkaart is vergrendeld."</string> <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"Simkaart is vergrendeld met PUK-code."</string> <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"Simkaart ontgrendelen…"</string> - <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Ontgrendeling via patroon."</string> - <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Ontgrendeling via pincode."</string> - <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Ontgrendeling via wachtwoord."</string> - <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Tekengebied voor patroon."</string> - <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Schuifgebied."</string> <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"Gebied voor pincode"</string> <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"Gebied voor sim-pincode"</string> <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"Gebied voor sim-pukcode"</string> diff --git a/packages/Keyguard/res/values-pa-rIN/strings.xml b/packages/Keyguard/res/values-pa-rIN/strings.xml index 8cf86a065e8d..16ca29c31172 100644 --- a/packages/Keyguard/res/values-pa-rIN/strings.xml +++ b/packages/Keyguard/res/values-pa-rIN/strings.xml @@ -46,11 +46,6 @@ <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM ਕਾਰਡ ਲੌਕ ਕੀਤਾ ਹੋਇਆ ਹੈ।"</string> <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM ਕਾਰਡ PUK-ਲੌਕਡ ਹੈ।"</string> <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"SIM ਕਾਰਡ ਅਨਲੌਕ ਕਰ ਰਿਹਾ ਹੈ…"</string> - <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"ਪੈਟਰਨ ਅਨਲੌਕ।"</string> - <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Pin ਅਨਲੌਕ।"</string> - <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"ਪਾਸਵਰਡ ਅਨਲੌਕ।"</string> - <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"ਪੈਟਰਨ ਖੇਤਰ।"</string> - <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"ਖੇਤਰ ਸਲਾਈਡ ਕਰੋ।"</string> <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"PIN ਖੇਤਰ"</string> <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"SIM PIN ਖੇਤਰ"</string> <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"SIM PUK ਖੇਤਰ"</string> diff --git a/packages/Keyguard/res/values-pl/strings.xml b/packages/Keyguard/res/values-pl/strings.xml index ee208508ac00..f0980da7d085 100644 --- a/packages/Keyguard/res/values-pl/strings.xml +++ b/packages/Keyguard/res/values-pl/strings.xml @@ -46,11 +46,6 @@ <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"Karta SIM jest zablokowana."</string> <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"Karta SIM jest zablokowana za pomocą kodu PUK."</string> <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"Odblokowuję kartę SIM…"</string> - <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Odblokowanie wzorem."</string> - <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Odblokowanie kodem PIN."</string> - <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Odblokowanie hasłem."</string> - <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Obszar wzoru."</string> - <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Obszar przesuwania."</string> <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"Miejsce na PIN"</string> <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"Miejsce na PIN do karty SIM"</string> <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"Miejsce na PUK do karty SIM"</string> diff --git a/packages/Keyguard/res/values-pt-rBR/strings.xml b/packages/Keyguard/res/values-pt-rBR/strings.xml index d7215c1a2c48..2663337cee82 100644 --- a/packages/Keyguard/res/values-pt-rBR/strings.xml +++ b/packages/Keyguard/res/values-pt-rBR/strings.xml @@ -46,11 +46,6 @@ <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"O cartão SIM está bloqueado."</string> <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"O cartão SIM está bloqueado pelo PUK."</string> <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"Desbloqueando o cartão SIM…"</string> - <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Desbloqueio com padrão."</string> - <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Desbloqueio com PIN."</string> - <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Desbloqueio com senha."</string> - <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Área do padrão."</string> - <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Área de deslize."</string> <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"Área do PIN"</string> <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"Área do PIN SIM"</string> <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"Área do PUK SIM"</string> diff --git a/packages/Keyguard/res/values-pt-rPT/strings.xml b/packages/Keyguard/res/values-pt-rPT/strings.xml index f0b2bbcd0d62..e417e07d94f1 100644 --- a/packages/Keyguard/res/values-pt-rPT/strings.xml +++ b/packages/Keyguard/res/values-pt-rPT/strings.xml @@ -46,11 +46,6 @@ <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"O cartão SIM está bloqueado."</string> <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"O cartão SIM está bloqueado por PUK."</string> <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"A desbloquear o cartão SIM..."</string> - <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Desbloqueio através de sequência."</string> - <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Desbloqueio através de PIN."</string> - <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Desbloqueio através de palavra-passe."</string> - <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Área da sequência."</string> - <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Área de deslize."</string> <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"Área do PIN"</string> <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"Área do PIN do SIM"</string> <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"Área do PUK do SIM"</string> diff --git a/packages/Keyguard/res/values-pt/strings.xml b/packages/Keyguard/res/values-pt/strings.xml index d7215c1a2c48..2663337cee82 100644 --- a/packages/Keyguard/res/values-pt/strings.xml +++ b/packages/Keyguard/res/values-pt/strings.xml @@ -46,11 +46,6 @@ <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"O cartão SIM está bloqueado."</string> <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"O cartão SIM está bloqueado pelo PUK."</string> <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"Desbloqueando o cartão SIM…"</string> - <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Desbloqueio com padrão."</string> - <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Desbloqueio com PIN."</string> - <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Desbloqueio com senha."</string> - <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Área do padrão."</string> - <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Área de deslize."</string> <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"Área do PIN"</string> <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"Área do PIN SIM"</string> <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"Área do PUK SIM"</string> diff --git a/packages/Keyguard/res/values-ro/strings.xml b/packages/Keyguard/res/values-ro/strings.xml index b1b142e548bc..09a066af2e90 100644 --- a/packages/Keyguard/res/values-ro/strings.xml +++ b/packages/Keyguard/res/values-ro/strings.xml @@ -46,11 +46,6 @@ <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"Cardul SIM este blocat."</string> <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"Cardul SIM este blocat cu codul PUK."</string> <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"Se deblochează cardul SIM…"</string> - <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Deblocare cu model."</string> - <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Deblocare cu PIN."</string> - <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Deblocare cu parolă."</string> - <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Zonă model."</string> - <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Zonă glisare."</string> <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"Zona codului PIN"</string> <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"Zona codului PIN al cardului SIM"</string> <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"Zona codului PUK al cardului SIM"</string> diff --git a/packages/Keyguard/res/values-ru/strings.xml b/packages/Keyguard/res/values-ru/strings.xml index 264e42ce6095..7466c6616032 100644 --- a/packages/Keyguard/res/values-ru/strings.xml +++ b/packages/Keyguard/res/values-ru/strings.xml @@ -46,11 +46,6 @@ <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM-карта заблокирована"</string> <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"Для разблокировки SIM-карты требуется PUK-код."</string> <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"Разблокировка SIM-карты…"</string> - <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Графический ключ"</string> - <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"PIN-код"</string> - <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Пароль"</string> - <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Область ввода графического ключа"</string> - <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Область слайдера"</string> <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"PIN-код"</string> <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"PIN-код SIM-карты"</string> <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"PUK-код SIM-карты"</string> diff --git a/packages/Keyguard/res/values-si-rLK/strings.xml b/packages/Keyguard/res/values-si-rLK/strings.xml index 607e8acd51b4..5f96e8c3f860 100644 --- a/packages/Keyguard/res/values-si-rLK/strings.xml +++ b/packages/Keyguard/res/values-si-rLK/strings.xml @@ -46,11 +46,6 @@ <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM පත අගුළු දමා ඇත."</string> <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM පත PUK අගුළු ලා ඇත."</string> <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"SIM පත අගුළු හරිමින්..."</string> - <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"රටා අගුළු ඇරීම."</string> - <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"PIN අගුළු ඇරීම."</string> - <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"මුරපද අගුළු ඇරීම."</string> - <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"රටා ප්රදේශය."</string> - <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"සර්පණ ප්රදේශය."</string> <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"PIN කොටස"</string> <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"SIM PIN කොටස"</string> <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"SIM PUK කොටස"</string> diff --git a/packages/Keyguard/res/values-sk/strings.xml b/packages/Keyguard/res/values-sk/strings.xml index 4cbfd51bdf87..82a4f1d46bde 100644 --- a/packages/Keyguard/res/values-sk/strings.xml +++ b/packages/Keyguard/res/values-sk/strings.xml @@ -46,11 +46,6 @@ <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM karta je uzamknutá."</string> <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM karta je uzamknutá pomocou kódu PUK."</string> <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"Prebieha odomykanie SIM karty..."</string> - <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Odomknutie vzorom."</string> - <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Odomknutie kódom PIN."</string> - <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Odomknutie heslom."</string> - <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Oblasť na zadanie bezpečnostného vzoru."</string> - <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Oblasť na prejdenie prstom."</string> <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"Oblasť kódu PIN"</string> <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"Oblasť kódu PIN SIM karty"</string> <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"Oblasť kódu PUK SIM karty"</string> diff --git a/packages/Keyguard/res/values-sl/strings.xml b/packages/Keyguard/res/values-sl/strings.xml index 91083f50bd8b..9100bd3e62ce 100644 --- a/packages/Keyguard/res/values-sl/strings.xml +++ b/packages/Keyguard/res/values-sl/strings.xml @@ -46,11 +46,6 @@ <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"Kartica SIM je zaklenjena."</string> <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"Kartica SIM je zaklenjena s kodo PUK."</string> <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"Odklepanje kartice SIM …"</string> - <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Odklepanje z vzorcem."</string> - <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Odklepanje s kodo PIN."</string> - <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Odklepanje z geslom."</string> - <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Območje vzorca."</string> - <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Območje podrsanja."</string> <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"Območje za kodo PIN"</string> <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"Območje za kodo PIN za SIM"</string> <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"Območje za kodo PUK za SIM"</string> diff --git a/packages/Keyguard/res/values-sq-rAL/strings.xml b/packages/Keyguard/res/values-sq-rAL/strings.xml index 7f4becbda4f0..31d31b79c76b 100644 --- a/packages/Keyguard/res/values-sq-rAL/strings.xml +++ b/packages/Keyguard/res/values-sq-rAL/strings.xml @@ -46,11 +46,6 @@ <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"Karta SIM është e kyçur."</string> <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"Karta SIM është e kyçur me PUK."</string> <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"Po shkyç kartën SIM…"</string> - <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Shkyçje me motiv."</string> - <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Shkyçje me PIN."</string> - <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Shkyçja e fjalëkalimit."</string> - <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Zona e motivit."</string> - <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Zonën e rrëshqitjes."</string> <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"Zona PIN"</string> <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"Zona PIN e kartës SIM"</string> <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"Zona e PUK-ut të kartës SIM"</string> diff --git a/packages/Keyguard/res/values-sr/strings.xml b/packages/Keyguard/res/values-sr/strings.xml index 62614a6fd5df..840cae79665a 100644 --- a/packages/Keyguard/res/values-sr/strings.xml +++ b/packages/Keyguard/res/values-sr/strings.xml @@ -46,11 +46,6 @@ <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM картица је закључана."</string> <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM картица је закључана PUK кодом."</string> <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"Откључавање SIM картице…"</string> - <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Откључавање шаблоном."</string> - <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Откључавање PIN-ом."</string> - <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Откључавање лозинком."</string> - <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Област шаблона."</string> - <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Област превлачења."</string> <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"Област за PIN"</string> <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"Област за PIN за SIM"</string> <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"Област за PUK за SIM"</string> diff --git a/packages/Keyguard/res/values-sv/strings.xml b/packages/Keyguard/res/values-sv/strings.xml index 378f0474c28e..527c8e65b384 100644 --- a/packages/Keyguard/res/values-sv/strings.xml +++ b/packages/Keyguard/res/values-sv/strings.xml @@ -46,11 +46,6 @@ <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM-kortet är låst."</string> <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM-kortet är PUK-låst."</string> <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"Låser upp SIM-kort …"</string> - <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Lås upp med grafiskt lösenord."</string> - <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Lås upp med PIN-kod."</string> - <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Lås upp med lösenord."</string> - <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Fält för grafiskt lösenord."</string> - <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Fält med dragreglage."</string> <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"Pinkodsområde"</string> <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"Pinkodsområde för SIM-kort"</string> <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"PUK-kodsområde för SIM-kort"</string> diff --git a/packages/Keyguard/res/values-sw/strings.xml b/packages/Keyguard/res/values-sw/strings.xml index b570e9f9f4eb..c2e7ac9f8824 100644 --- a/packages/Keyguard/res/values-sw/strings.xml +++ b/packages/Keyguard/res/values-sw/strings.xml @@ -46,11 +46,6 @@ <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM kadi imefungwa."</string> <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM kadi imefungwa na PUK."</string> <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"Inafungua SIM kadi..."</string> - <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Kufungua kwa ruwaza."</string> - <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Kufungua kwa PIN."</string> - <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Kufungua kwa nenosiri."</string> - <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Eneo la ruwaza."</string> - <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Eneo la slaidi."</string> <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"Eneo la PIN"</string> <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"Eneo la PIN ya SIM"</string> <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"Eneo la PUK ya SIM"</string> diff --git a/packages/Keyguard/res/values-ta-rIN/strings.xml b/packages/Keyguard/res/values-ta-rIN/strings.xml index 2e3f588955fd..c80ddce068c3 100644 --- a/packages/Keyguard/res/values-ta-rIN/strings.xml +++ b/packages/Keyguard/res/values-ta-rIN/strings.xml @@ -46,11 +46,6 @@ <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"சிம் கார்டு பூட்டப்பட்டுள்ளது."</string> <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"சிம் கார்டு PUK ஆல் பூட்டப்பட்டது."</string> <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"சிம் கார்டின் தடையைநீக்குகிறது..."</string> - <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"வடிவம் மூலம் திறத்தல்."</string> - <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Pin மூலம் திறத்தல்."</string> - <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"கடவுச்சொல் மூலம் திறத்தல்."</string> - <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"வடிவப் பகுதி."</string> - <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"ஸ்லைடு பகுதி."</string> <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"PIN பகுதி"</string> <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"சிம் PIN பகுதி"</string> <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"சிம் PUK பகுதி"</string> diff --git a/packages/Keyguard/res/values-te-rIN/strings.xml b/packages/Keyguard/res/values-te-rIN/strings.xml index 6c521aad79c4..a72a85b1851e 100644 --- a/packages/Keyguard/res/values-te-rIN/strings.xml +++ b/packages/Keyguard/res/values-te-rIN/strings.xml @@ -46,11 +46,6 @@ <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"సిమ్ కార్డు లాక్ చేయబడింది."</string> <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"సిమ్ కార్డు PUK లాక్ చేయబడింది."</string> <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"సిమ్ కార్డును అన్లాక్ చేస్తోంది…"</string> - <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"నమూనా అన్లాక్."</string> - <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"పిన్ అన్లాక్."</string> - <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"పాస్వర్డ్ అన్లాక్."</string> - <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"నమూనా ప్రాంతం."</string> - <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"స్లయిడ్ ప్రాంతం."</string> <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"PIN ప్రాంతం"</string> <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"SIM PIN ప్రాంతం"</string> <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"SIM PUK ప్రాంతం"</string> diff --git a/packages/Keyguard/res/values-th/strings.xml b/packages/Keyguard/res/values-th/strings.xml index 1799fe8ddec5..e094d3503f2d 100644 --- a/packages/Keyguard/res/values-th/strings.xml +++ b/packages/Keyguard/res/values-th/strings.xml @@ -46,11 +46,6 @@ <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"ซิมการ์ดถูกล็อก"</string> <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"ซิมการ์ดถูกล็อกด้วย PUK"</string> <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"กำลังปลดล็อกซิมการ์ด…"</string> - <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"การปลดล็อกด้วยรูปแบบ"</string> - <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"การปลดล็อกด้วย PIN"</string> - <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"การปลดล็อกด้วยรหัสผ่าน"</string> - <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"พื้นที่สำหรับรูปแบบ"</string> - <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"พื้นที่สำหรับการเลื่อน"</string> <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"พื้นที่ PIN"</string> <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"พื้นที่ PIN ของซิม"</string> <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"พื้นที่ PUK ของซิม"</string> diff --git a/packages/Keyguard/res/values-tl/strings.xml b/packages/Keyguard/res/values-tl/strings.xml index 39cad7274c39..73492e2621b8 100644 --- a/packages/Keyguard/res/values-tl/strings.xml +++ b/packages/Keyguard/res/values-tl/strings.xml @@ -46,11 +46,6 @@ <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"Naka-lock ang SIM card."</string> <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"Naka-lock ang SIM card gamit ang PUK."</string> <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"Ina-unlock ang SIM card…"</string> - <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Pag-unlock ng pattern."</string> - <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Pag-unlock ng pin."</string> - <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Pag-unlock ng password."</string> - <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Bahagi ng pattern."</string> - <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Bahagi ng slide."</string> <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"Lugar ng PIN"</string> <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"Lugar ng PIN ng SIM"</string> <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"Lugar ng PUK ng SIM"</string> diff --git a/packages/Keyguard/res/values-tr/strings.xml b/packages/Keyguard/res/values-tr/strings.xml index ffcbd12cf158..3ef07056a434 100644 --- a/packages/Keyguard/res/values-tr/strings.xml +++ b/packages/Keyguard/res/values-tr/strings.xml @@ -46,11 +46,6 @@ <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM kart kilitli."</string> <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM kart PUK kilidi devrede."</string> <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"SIM kart kilidi açılıyor…"</string> - <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Desenle kilit açma."</string> - <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Pin koduyla kilit açma."</string> - <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Şifreyle kilit açma."</string> - <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Desen alanı."</string> - <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Kaydırma alanı."</string> <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"PIN alanı"</string> <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"SIM PIN alanı"</string> <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"SIM PUK alanı"</string> diff --git a/packages/Keyguard/res/values-uk/strings.xml b/packages/Keyguard/res/values-uk/strings.xml index be19281fec33..a50868960a8c 100644 --- a/packages/Keyguard/res/values-uk/strings.xml +++ b/packages/Keyguard/res/values-uk/strings.xml @@ -46,11 +46,6 @@ <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM-карту заблоковано."</string> <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM-карту заблоковано PUK-кодом."</string> <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"Розблокування SIM-карти…"</string> - <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Розблокування ключем."</string> - <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Розблокування PIN-кодом."</string> - <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Розблокування паролем."</string> - <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Область ключа."</string> - <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Область повзунка."</string> <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"PIN-код"</string> <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"PIN-код SIM-карти"</string> <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"PUK-код SIM-карти"</string> diff --git a/packages/Keyguard/res/values-ur-rPK/strings.xml b/packages/Keyguard/res/values-ur-rPK/strings.xml index 63f4e85034f2..1070d58a8dc5 100644 --- a/packages/Keyguard/res/values-ur-rPK/strings.xml +++ b/packages/Keyguard/res/values-ur-rPK/strings.xml @@ -46,11 +46,6 @@ <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM کارڈ مقفل ہے۔"</string> <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM کارڈ PUK-مقفل ہے۔"</string> <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"SIM کارڈ غیر مقفل کیا جا رہا ہے…"</string> - <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"پیٹرن کے ذریعے غیر مقفل کریں۔"</string> - <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"پن کے ذریعے غیر مقفل کریں۔"</string> - <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"پاس ورڈ کے ذریعہ غیر مقفل کریں۔"</string> - <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"پیٹرن کا علاقہ۔"</string> - <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"سلائیڈ کرنے کا علاقہ۔"</string> <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"PIN کا علاقہ"</string> <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"SIM PIN کا علاقہ"</string> <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"SIM PUK کا علاقہ"</string> diff --git a/packages/Keyguard/res/values-uz-rUZ/strings.xml b/packages/Keyguard/res/values-uz-rUZ/strings.xml index ad71a56651c3..a9df331487e6 100644 --- a/packages/Keyguard/res/values-uz-rUZ/strings.xml +++ b/packages/Keyguard/res/values-uz-rUZ/strings.xml @@ -46,11 +46,6 @@ <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM karta qulflangan."</string> <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM karta PUK kod bilan qulflangan."</string> <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"SIM karta qulfi ochilmoqda…"</string> - <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Grafik kalit bilan ochish."</string> - <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Pin qulfini ochish."</string> - <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Parolli qulfni ochish."</string> - <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Grafik kalit chiziladigan hudud."</string> - <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Maydonni silang"</string> <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"PIN-kod maydoni"</string> <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"SIM karta PIN kodi maydoni"</string> <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"SIM karta PUK kodi maydoni"</string> diff --git a/packages/Keyguard/res/values-vi/strings.xml b/packages/Keyguard/res/values-vi/strings.xml index ad3da9fbf32d..c6d2bd808e8b 100644 --- a/packages/Keyguard/res/values-vi/strings.xml +++ b/packages/Keyguard/res/values-vi/strings.xml @@ -46,11 +46,6 @@ <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"Thẻ SIM đã bị khóa."</string> <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"Thẻ SIM đã bị khóa PUK."</string> <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"Đang mở khóa thẻ SIM…"</string> - <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Mở khóa bằng hình."</string> - <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Mở khóa bằng mã pin."</string> - <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Mở khóa bằng mật khẩu."</string> - <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Khu vực hình."</string> - <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Khu vực trượt."</string> <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"Khu vực mã PIN"</string> <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"Khu vực mã PIN của SIM"</string> <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"Khu vực PUK của SIM"</string> diff --git a/packages/Keyguard/res/values-zh-rCN/strings.xml b/packages/Keyguard/res/values-zh-rCN/strings.xml index 274d9e69492e..0723ab19e7b6 100644 --- a/packages/Keyguard/res/values-zh-rCN/strings.xml +++ b/packages/Keyguard/res/values-zh-rCN/strings.xml @@ -46,11 +46,6 @@ <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM卡已被锁定。"</string> <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM卡已被PUK码锁定。"</string> <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"正在解锁SIM卡..."</string> - <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"图案解锁。"</string> - <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"PIN码解锁。"</string> - <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"密码解锁。"</string> - <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"图案区域。"</string> - <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"滑动区域。"</string> <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"PIN 码区域"</string> <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"SIM 卡 PIN 码区域"</string> <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"SIM 卡 PUK 码区域"</string> diff --git a/packages/Keyguard/res/values-zh-rHK/strings.xml b/packages/Keyguard/res/values-zh-rHK/strings.xml index 7d511540d7ec..5b1903b4b961 100644 --- a/packages/Keyguard/res/values-zh-rHK/strings.xml +++ b/packages/Keyguard/res/values-zh-rHK/strings.xml @@ -46,11 +46,6 @@ <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM 卡處於鎖定狀態。"</string> <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM 卡處於 PUK 鎖定狀態。"</string> <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"正在解開上鎖的 SIM 卡..."</string> - <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"圖案解鎖。"</string> - <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"PIN 解鎖。"</string> - <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"密碼解鎖。"</string> - <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"圖案區域。"</string> - <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"滑動區域。"</string> <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"PIN 區域"</string> <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"SIM PIN 區域"</string> <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"SIM PUK 區域"</string> diff --git a/packages/Keyguard/res/values-zh-rTW/strings.xml b/packages/Keyguard/res/values-zh-rTW/strings.xml index 50895f3da3b9..388f8e17872a 100644 --- a/packages/Keyguard/res/values-zh-rTW/strings.xml +++ b/packages/Keyguard/res/values-zh-rTW/strings.xml @@ -46,11 +46,6 @@ <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"SIM 卡處於鎖定狀態。"</string> <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"SIM 卡處於 PUK 鎖定狀態"</string> <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"正在解除 SIM 卡鎖定..."</string> - <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"圖案解鎖。"</string> - <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"PIN 解鎖。"</string> - <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"密碼解鎖。"</string> - <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"圖案區域。"</string> - <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"滑動區域。"</string> <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"PIN 區"</string> <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"SIM 卡 PIN 區"</string> <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"SIM 卡 PUK 區"</string> diff --git a/packages/Keyguard/res/values-zu/strings.xml b/packages/Keyguard/res/values-zu/strings.xml index c5f2a85bd4b8..a9b62634548a 100644 --- a/packages/Keyguard/res/values-zu/strings.xml +++ b/packages/Keyguard/res/values-zu/strings.xml @@ -46,11 +46,6 @@ <string name="keyguard_sim_locked_message" msgid="6875773413306380902">"Ikhadi le-SIM likhiyiwe."</string> <string name="keyguard_sim_puk_locked_message" msgid="3747232467471801633">"Ikhadi le-SIM likhiywe nge-PUK."</string> <string name="keyguard_sim_unlock_progress_dialog_message" msgid="7975221805033614426">"Ivula ikhadi le-SIM..."</string> - <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"Ukuvula ngephethini."</string> - <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Ukuvula ngephinikhodi."</string> - <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Ukuvula ngephasiwedi."</string> - <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Indawo yephethini."</string> - <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Indawo yokushelelisa."</string> <string name="keyguard_accessibility_pin_area" msgid="7903959476607833485">"Indawo yephinikhodi"</string> <string name="keyguard_accessibility_sim_pin_area" msgid="3887780775111719336">"Indawo yephinikhodi ye-SIM"</string> <string name="keyguard_accessibility_sim_puk_area" msgid="1880823406954996207">"Indawo ye-SIM PUK"</string> diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardPasswordView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardPasswordView.java index b75f52987a92..ddccc14a60f0 100644 --- a/packages/Keyguard/src/com/android/keyguard/KeyguardPasswordView.java +++ b/packages/Keyguard/src/com/android/keyguard/KeyguardPasswordView.java @@ -42,16 +42,21 @@ import java.util.List; * Displays an alphanumeric (latin-1) key entry for the user to enter * an unlock password */ - public class KeyguardPasswordView extends KeyguardAbsKeyInputView implements KeyguardSecurityView, OnEditorActionListener, TextWatcher { private final boolean mShowImeAtScreenOn; private final int mDisappearYTranslation; + // A delay constant to be used in a workaround for the situation where InputMethodManagerService + // is not switched to the new user yet. + // TODO: Remove this by ensuring such a race condition never happens. + private static final int DELAY_MILLIS_TO_REEVALUATE_IME_SWITCH_ICON = 500; // 500ms + InputMethodManager mImm; private TextView mPasswordEntry; private TextViewInputDisabler mPasswordEntryDisabler; + private View mSwitchImeButton; private Interpolator mLinearOutSlowInInterpolator; private Interpolator mFastOutLinearInInterpolator; @@ -141,12 +146,31 @@ public class KeyguardPasswordView extends KeyguardAbsKeyInputView mPasswordEntry.requestFocus(); } + private void updateSwitchImeButton() { + // If there's more than one IME, enable the IME switcher button + final boolean wasVisible = mSwitchImeButton.getVisibility() == View.VISIBLE; + final boolean shouldBeVisible = hasMultipleEnabledIMEsOrSubtypes(mImm, false); + if (wasVisible != shouldBeVisible) { + mSwitchImeButton.setVisibility(shouldBeVisible ? View.VISIBLE : View.GONE); + } + + // TODO: Check if we still need this hack. + // If no icon is visible, reset the start margin on the password field so the text is + // still centered. + if (mSwitchImeButton.getVisibility() != View.VISIBLE) { + android.view.ViewGroup.LayoutParams params = mPasswordEntry.getLayoutParams(); + if (params instanceof MarginLayoutParams) { + final MarginLayoutParams mlp = (MarginLayoutParams) params; + mlp.setMarginStart(0); + mPasswordEntry.setLayoutParams(params); + } + } + } + @Override protected void onFinishInflate() { super.onFinishInflate(); - boolean imeOrDeleteButtonVisible = false; - mImm = (InputMethodManager) getContext().getSystemService( Context.INPUT_METHOD_SERVICE); @@ -171,31 +195,29 @@ public class KeyguardPasswordView extends KeyguardAbsKeyInputView mPasswordEntry.requestFocus(); + mSwitchImeButton = findViewById(R.id.switch_ime_button); + mSwitchImeButton.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + mCallback.userActivity(); // Leave the screen on a bit longer + // Do not show auxiliary subtypes in password lock screen. + mImm.showInputMethodPicker(false /* showAuxiliarySubtypes */); + } + }); + // If there's more than one IME, enable the IME switcher button - View switchImeButton = findViewById(R.id.switch_ime_button); - if (switchImeButton != null && hasMultipleEnabledIMEsOrSubtypes(mImm, false)) { - switchImeButton.setVisibility(View.VISIBLE); - imeOrDeleteButtonVisible = true; - switchImeButton.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - mCallback.userActivity(); // Leave the screen on a bit longer - // Do not show auxiliary subtypes in password lock screen. - mImm.showInputMethodPicker(false /* showAuxiliarySubtypes */); - } - }); - } + updateSwitchImeButton(); - // If no icon is visible, reset the start margin on the password field so the text is - // still centered. - if (!imeOrDeleteButtonVisible) { - android.view.ViewGroup.LayoutParams params = mPasswordEntry.getLayoutParams(); - if (params instanceof MarginLayoutParams) { - final MarginLayoutParams mlp = (MarginLayoutParams) params; - mlp.setMarginStart(0); - mPasswordEntry.setLayoutParams(params); + // When we the current user is switching, InputMethodManagerService sometimes has not + // switched internal state yet here. As a quick workaround, we check the keyboard state + // again. + // TODO: Remove this workaround by ensuring such a race condition never happens. + postDelayed(new Runnable() { + @Override + public void run() { + updateSwitchImeButton(); } - } + }, DELAY_MILLIS_TO_REEVALUATE_IME_SWITCH_ICON); } @Override diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityView.java index aa74940492f2..829084202f5a 100644 --- a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityView.java +++ b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityView.java @@ -49,11 +49,6 @@ public interface KeyguardSecurityView { int PROMPT_REASON_AFTER_LOCKOUT = 5; /** - * Some auth is required because a single wrong credential has been tried. - */ - int PROMPT_REASON_WRONG_CREDENTIAL = 6; - - /** * Interface back to keyguard to tell it when security * @param callback */ diff --git a/packages/SettingsLib/res/values-ky-rKG/arrays.xml b/packages/SettingsLib/res/values-ky-rKG/arrays.xml index a06ecfba0fda..1aadb9b0a52b 100644 --- a/packages/SettingsLib/res/values-ky-rKG/arrays.xml +++ b/packages/SettingsLib/res/values-ky-rKG/arrays.xml @@ -147,7 +147,7 @@ <string-array name="track_frame_time_entries"> <item msgid="2193584639058893150">"Өчүк"</item> <item msgid="2751513398307949636">"Экранда тилке катары"</item> - <item msgid="2355151170975410323">"Төмөнкүдө <xliff:g id="AS_TYPED_COMMAND">adb shell dumpsys gfxinfo</xliff:g>"</item> + <item msgid="2355151170975410323">"Төмөнкүдө: <xliff:g id="AS_TYPED_COMMAND">adb shell dumpsys gfxinfo</xliff:g>"</item> </string-array> <string-array name="debug_hw_overdraw_entries"> <item msgid="8190572633763871652">"Өчүк"</item> diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml index 3838143cc193..3bdb6fbdb3cb 100644 --- a/packages/SettingsLib/res/values/strings.xml +++ b/packages/SettingsLib/res/values/strings.xml @@ -863,4 +863,7 @@ <!-- Label for Help and feedback menu item --> <string name="help_feedback_label">Help & feedback</string> + <!-- Content description for drawer menu button [CHAR_LIMIT=30]--> + <string name="content_description_menu_button">Menu</string> + </resources> diff --git a/packages/SettingsLib/src/com/android/settingslib/NetworkPolicyEditor.java b/packages/SettingsLib/src/com/android/settingslib/NetworkPolicyEditor.java index cf08f5000b8f..687b3fc68542 100644 --- a/packages/SettingsLib/src/com/android/settingslib/NetworkPolicyEditor.java +++ b/packages/SettingsLib/src/com/android/settingslib/NetworkPolicyEditor.java @@ -167,7 +167,7 @@ public class NetworkPolicyEditor { return (policy != null) ? policy.warningBytes : WARNING_DISABLED; } - public void setPolicyWarningBytes(NetworkTemplate template, long warningBytes) { + private void setPolicyWarningBytesInner(NetworkTemplate template, long warningBytes) { final NetworkPolicy policy = getOrCreatePolicy(template); policy.warningBytes = warningBytes; policy.inferred = false; @@ -175,12 +175,28 @@ public class NetworkPolicyEditor { writeAsync(); } + public void setPolicyWarningBytes(NetworkTemplate template, long warningBytes) { + long limitBytes = getPolicyLimitBytes(template); + + // If the warningBytes are larger than limitBytes, set the warningBytes to limitBytes + warningBytes = Math.min(warningBytes, limitBytes); + setPolicyWarningBytesInner(template, warningBytes); + } + public long getPolicyLimitBytes(NetworkTemplate template) { final NetworkPolicy policy = getPolicy(template); return (policy != null) ? policy.limitBytes : LIMIT_DISABLED; } + public void setPolicyLimitBytes(NetworkTemplate template, long limitBytes) { + long warningBytes = getPolicyWarningBytes(template); + + // If the warningBytes are larger than limitBytes, set the warningBytes to limitBytes + if (warningBytes > limitBytes) { + setPolicyWarningBytesInner(template, limitBytes); + } + final NetworkPolicy policy = getOrCreatePolicy(template); policy.limitBytes = limitBytes; policy.inferred = false; diff --git a/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java b/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java index 6658c14bd1cd..a50b366c26ac 100644 --- a/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java +++ b/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java @@ -226,6 +226,7 @@ public class SettingsDrawerActivity extends Activity { public void showMenuIcon() { mShowingMenu = true; getActionBar().setHomeAsUpIndicator(R.drawable.ic_menu); + getActionBar().setHomeActionContentDescription(R.string.content_description_menu_button); getActionBar().setDisplayHomeAsUpEnabled(true); } diff --git a/packages/Shell/res/values-ms-rMY/strings.xml b/packages/Shell/res/values-ms-rMY/strings.xml index f0c19dc7e1c7..a1cf3eabf729 100644 --- a/packages/Shell/res/values-ms-rMY/strings.xml +++ b/packages/Shell/res/values-ms-rMY/strings.xml @@ -40,5 +40,5 @@ <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> - <string name="bugreport_intent_chooser_title" msgid="7605709494790894076">"Kongsi Laporan pepijat?"</string> + <string name="bugreport_intent_chooser_title" msgid="7605709494790894076">"Kongsi Laporan pepijat"</string> </resources> diff --git a/packages/Shell/tests/Android.mk b/packages/Shell/tests/Android.mk index 1e0eaace35da..872eb7ac7dcf 100644 --- a/packages/Shell/tests/Android.mk +++ b/packages/Shell/tests/Android.mk @@ -8,7 +8,9 @@ LOCAL_SRC_FILES := $(call all-java-files-under, src) LOCAL_JAVA_LIBRARIES := android.test.runner -LOCAL_STATIC_JAVA_LIBRARIES := ub-uiautomator +LOCAL_STATIC_JAVA_LIBRARIES := \ + android-support-test \ + ub-uiautomator \ LOCAL_PACKAGE_NAME := ShellTests LOCAL_INSTRUMENTATION_FOR := Shell diff --git a/packages/Shell/tests/AndroidManifest.xml b/packages/Shell/tests/AndroidManifest.xml index 54b0802e1504..6d564c640fcd 100644 --- a/packages/Shell/tests/AndroidManifest.xml +++ b/packages/Shell/tests/AndroidManifest.xml @@ -36,7 +36,7 @@ </activity> </application> - <instrumentation android:name="android.test.InstrumentationTestRunner" + <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner" android:targetPackage="com.android.shell" android:label="Tests for Shell" /> diff --git a/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java b/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java index 902c71d64ae9..dde71ebe5530 100644 --- a/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java +++ b/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java @@ -36,6 +36,13 @@ import static com.android.shell.BugreportProgressService.INTENT_BUGREPORT_STARTE import static com.android.shell.BugreportProgressService.POLLING_FREQUENCY; import static com.android.shell.BugreportProgressService.SCREENSHOT_DELAY_SECONDS; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + import java.io.BufferedOutputStream; import java.io.BufferedWriter; import java.io.ByteArrayOutputStream; @@ -56,6 +63,13 @@ import java.util.zip.ZipOutputStream; import libcore.io.Streams; +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TestName; +import org.junit.runner.RunWith; + import android.app.ActivityManager; import android.app.ActivityManager.RunningServiceInfo; import android.app.Instrumentation; @@ -68,11 +82,12 @@ import android.os.Bundle; import android.os.SystemClock; import android.os.SystemProperties; import android.service.notification.StatusBarNotification; +import android.support.test.InstrumentationRegistry; +import android.support.test.filters.LargeTest; +import android.support.test.runner.AndroidJUnit4; import android.support.test.uiautomator.UiDevice; import android.support.test.uiautomator.UiObject; import android.support.test.uiautomator.UiObjectNotFoundException; -import android.test.InstrumentationTestCase; -import android.test.suitebuilder.annotation.LargeTest; import android.text.TextUtils; import android.text.format.DateUtils; import android.util.Log; @@ -96,7 +111,8 @@ import com.android.shell.ActionSendMultipleConsumerActivity.CustomActionSendMult * <strong>NOTE</strong>: these tests only work if the device is unlocked. */ @LargeTest -public class BugreportReceiverTest extends InstrumentationTestCase { +@RunWith(AndroidJUnit4.class) +public class BugreportReceiverTest { private static final String TAG = "BugreportReceiverTest"; // Timeout for UI operations, in milliseconds. @@ -149,9 +165,10 @@ public class BugreportReceiverTest extends InstrumentationTestCase { private UiBot mUiBot; private CustomActionSendMultipleListener mListener; - @Override - protected void setUp() throws Exception { - super.setUp(); + @Rule public TestName mName = new TestName(); + + @Before + public void setUp() throws Exception { Log.i(TAG, getName() + ".setup()"); Instrumentation instrumentation = getInstrumentation(); mContext = instrumentation.getTargetContext(); @@ -181,13 +198,13 @@ public class BugreportReceiverTest extends InstrumentationTestCase { mUiBot.turnScreenOn(); } - @Override - protected void tearDown() throws Exception { + @After + public void tearDown() throws Exception { Log.i(TAG, getName() + ".tearDown()"); cancelExistingNotifications(); - super.tearDown(); } + @Test public void testProgress() throws Exception { resetProperties(); sendBugreportStarted(1000); @@ -233,6 +250,7 @@ public class BugreportReceiverTest extends InstrumentationTestCase { assertServiceNotRunning(); } + @Test public void testProgress_cancel() throws Exception { resetProperties(); sendBugreportStarted(1000); @@ -249,6 +267,7 @@ public class BugreportReceiverTest extends InstrumentationTestCase { waitForService(false); } + @Test public void testProgress_takeExtraScreenshot() throws Exception { resetProperties(); sendBugreportStarted(1000); @@ -267,6 +286,7 @@ public class BugreportReceiverTest extends InstrumentationTestCase { assertServiceNotRunning(); } + @Test public void testScreenshotFinishesAfterBugreport() throws Exception { resetProperties(); @@ -286,6 +306,7 @@ public class BugreportReceiverTest extends InstrumentationTestCase { assertServiceNotRunning(); } + @Test public void testProgress_changeDetailsInvalidInput() throws Exception { resetProperties(); sendBugreportStarted(1000); @@ -331,6 +352,7 @@ public class BugreportReceiverTest extends InstrumentationTestCase { assertServiceNotRunning(); } + @Test public void testProgress_cancelBugClosesDetailsDialog() throws Exception { resetProperties(); sendBugreportStarted(1000); @@ -346,10 +368,12 @@ public class BugreportReceiverTest extends InstrumentationTestCase { assertServiceNotRunning(); } + @Test public void testProgress_changeDetailsPlainBugreport() throws Exception { changeDetailsTest(true); } + @Test public void testProgress_changeDetailsZippedBugreport() throws Exception { changeDetailsTest(false); } @@ -383,10 +407,12 @@ public class BugreportReceiverTest extends InstrumentationTestCase { assertServiceNotRunning(); } + @Test public void testProgress_changeJustDetailsTouchingDetails() throws Exception { changeJustDetailsTest(true); } + @Test public void testProgress_changeJustDetailsTouchingNotification() throws Exception { changeJustDetailsTest(false); } @@ -410,6 +436,7 @@ public class BugreportReceiverTest extends InstrumentationTestCase { assertServiceNotRunning(); } + @Test public void testProgress_changeJustDetailsIsClearedOnSecondBugreport() throws Exception { resetProperties(); sendBugreportStarted(ID, PID, NAME, 1000); @@ -453,6 +480,7 @@ public class BugreportReceiverTest extends InstrumentationTestCase { * Tests the scenario where the initial screenshot and dumpstate are finished while the user * is changing the info in the details screen. */ + @Test public void testProgress_bugreportAndScreenshotFinishedWhileChangingDetails() throws Exception { bugreportFinishedWhileChangingDetailsTest(false); } @@ -461,6 +489,7 @@ public class BugreportReceiverTest extends InstrumentationTestCase { * Tests the scenario where dumpstate is finished while the user is changing the info in the * details screen, but the initial screenshot finishes afterwards. */ + @Test public void testProgress_bugreportFinishedWhileChangingDetails() throws Exception { bugreportFinishedWhileChangingDetailsTest(true); } @@ -500,14 +529,17 @@ public class BugreportReceiverTest extends InstrumentationTestCase { assertServiceNotRunning(); } + @Test public void testBugreportFinished_withWarningFirstTime() throws Exception { bugreportFinishedWithWarningTest(null); } + @Test public void testBugreportFinished_withWarningUnknownState() throws Exception { bugreportFinishedWithWarningTest(STATE_UNKNOWN); } + @Test public void testBugreportFinished_withWarningShowAgain() throws Exception { bugreportFinishedWithWarningTest(STATE_SHOW); } @@ -560,6 +592,7 @@ public class BugreportReceiverTest extends InstrumentationTestCase { assertEquals("Didn't change state", STATE_HIDE, newState); } + @Test public void testShareBugreportAfterServiceDies() throws Exception { sendBugreportFinished(NO_ID, mPlainTextPath, NO_SCREENSHOT); waitForService(false); @@ -567,21 +600,25 @@ public class BugreportReceiverTest extends InstrumentationTestCase { assertActionSendMultiple(extras, BUGREPORT_CONTENT, NO_SCREENSHOT); } + @Test public void testBugreportFinished_plainBugreportAndScreenshot() throws Exception { Bundle extras = sendBugreportFinishedAndGetSharedIntent(mPlainTextPath, mScreenshotPath); assertActionSendMultiple(extras, BUGREPORT_CONTENT, SCREENSHOT_CONTENT); } + @Test public void testBugreportFinished_zippedBugreportAndScreenshot() throws Exception { Bundle extras = sendBugreportFinishedAndGetSharedIntent(mZipPath, mScreenshotPath); assertActionSendMultiple(extras, BUGREPORT_CONTENT, SCREENSHOT_CONTENT); } + @Test public void testBugreportFinished_plainBugreportAndNoScreenshot() throws Exception { Bundle extras = sendBugreportFinishedAndGetSharedIntent(mPlainTextPath, NO_SCREENSHOT); assertActionSendMultiple(extras, BUGREPORT_CONTENT, NO_SCREENSHOT); } + @Test public void testBugreportFinished_zippedBugreportAndNoScreenshot() throws Exception { Bundle extras = sendBugreportFinishedAndGetSharedIntent(mZipPath, NO_SCREENSHOT); assertActionSendMultiple(extras, BUGREPORT_CONTENT, NO_SCREENSHOT); @@ -1001,6 +1038,14 @@ public class BugreportReceiverTest extends InstrumentationTestCase { mUiBot.assertNotVisibleById("android:id/alertTitle"); } + private String getName() { + return mName.getMethodName(); + } + + private Instrumentation getInstrumentation() { + return InstrumentationRegistry.getInstrumentation(); + } + private static void sleep(long ms) { Log.d(TAG, "sleeping for " + ms + "ms"); SystemClock.sleep(ms); diff --git a/packages/SystemUI/res/layout/tv_pip_controls.xml b/packages/SystemUI/res/layout/tv_pip_controls.xml index 0a2f32048e02..49119fb2bda8 100644 --- a/packages/SystemUI/res/layout/tv_pip_controls.xml +++ b/packages/SystemUI/res/layout/tv_pip_controls.xml @@ -41,5 +41,6 @@ android:layout_height="wrap_content" android:layout_marginStart="-50dp" android:src="@drawable/ic_pause_white_24dp" - android:text="@string/pip_pause" /> + android:text="@string/pip_pause" + android:visibility="gone" /> </merge> diff --git a/packages/SystemUI/res/layout/volume_zen_footer.xml b/packages/SystemUI/res/layout/volume_zen_footer.xml index ea26bba89432..775b1576b763 100644 --- a/packages/SystemUI/res/layout/volume_zen_footer.xml +++ b/packages/SystemUI/res/layout/volume_zen_footer.xml @@ -18,7 +18,8 @@ android:id="@+id/volume_zen_footer" android:layout_width="match_parent" android:layout_height="wrap_content" - android:orientation="vertical" > <!-- extends LinearLayout --> + android:orientation="vertical" + android:paddingBottom="8dp" > <!-- extends LinearLayout --> <View android:id="@+id/zen_embedded_divider" diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml index 48935987ae7c..fe27459c3d01 100644 --- a/packages/SystemUI/res/values-fi/strings.xml +++ b/packages/SystemUI/res/values-fi/strings.xml @@ -602,7 +602,7 @@ <string name="keycode_description" msgid="1403795192716828949">"Näppäinkoodi-painikkeet sallivat näppäimistön näppäimien lisäämisen navigointipalkkiin. Kun painiketta painetaan, se jäljittelee valittua näppäintä. Valitse ensin painikkeen kohteena oleva näppäin, sitten painikkeessa näkyvä kuva."</string> <string name="select_keycode" msgid="7413765103381924584">"Valitse näppäimistön näppäin"</string> <string name="preview" msgid="9077832302472282938">"Esikatselu"</string> - <string name="drag_to_add_tiles" msgid="7058945779098711293">"Lisää osioita vetämällä."</string> + <string name="drag_to_add_tiles" msgid="7058945779098711293">"Lisää osioita vetämällä"</string> <string name="drag_to_remove_tiles" msgid="3361212377437088062">"Poista vetämällä tähän."</string> <string name="qs_edit" msgid="2232596095725105230">"Muokkaa"</string> <string name="tuner_time" msgid="6572217313285536011">"Aika"</string> diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml index 5acc1776d6dc..a93c3e20f2bc 100644 --- a/packages/SystemUI/res/values-fr/strings.xml +++ b/packages/SystemUI/res/values-fr/strings.xml @@ -313,7 +313,7 @@ <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Notifications"</string> <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Lampe de poche"</string> <string name="quick_settings_cellular_detail_title" msgid="8575062783675171695">"Données mobiles"</string> - <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Consommation des données"</string> + <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Conso des données"</string> <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Données restantes"</string> <string name="quick_settings_cellular_detail_over_limit" msgid="967669665390990427">"Limite dépassée"</string> <string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"<xliff:g id="DATA_USED">%s</xliff:g> utilisés"</string> diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml index de96cb0bcac1..a15ba26be0a2 100644 --- a/packages/SystemUI/res/values-vi/strings.xml +++ b/packages/SystemUI/res/values-vi/strings.xml @@ -309,7 +309,7 @@ <string name="quick_settings_tethering_label" msgid="7153452060448575549">"Đang dùng làm điểm truy cập Internet"</string> <string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Điểm phát sóng"</string> <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Thông báo"</string> - <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Đèn nháy"</string> + <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Đèn pin"</string> <string name="quick_settings_cellular_detail_title" msgid="8575062783675171695">"Dữ liệu di động"</string> <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"Sử dụng dữ liệu"</string> <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"Dữ liệu còn lại"</string> diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java index 8b592c2335e3..c4ef80f004b5 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java +++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java @@ -86,7 +86,6 @@ import java.util.List; import static android.provider.Settings.System.SCREEN_OFF_TIMEOUT; import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.SOME_AUTH_REQUIRED_AFTER_USER_REQUEST; -import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.SOME_AUTH_REQUIRED_AFTER_WRONG_CREDENTIAL; import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW; import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_LOCKOUT; @@ -626,10 +625,7 @@ public class KeyguardViewMediator extends SystemUI { return KeyguardSecurityView.PROMPT_REASON_USER_REQUEST; } else if (any && (strongAuth & STRONG_AUTH_REQUIRED_AFTER_LOCKOUT) != 0) { return KeyguardSecurityView.PROMPT_REASON_AFTER_LOCKOUT; - } else if (trust && (strongAuth & SOME_AUTH_REQUIRED_AFTER_WRONG_CREDENTIAL) != 0) { - return KeyguardSecurityView.PROMPT_REASON_WRONG_CREDENTIAL; } - return KeyguardSecurityView.PROMPT_REASON_NONE; } }; diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSContainer.java b/packages/SystemUI/src/com/android/systemui/qs/QSContainer.java index ac90ce73fa03..19a5d522f530 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSContainer.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSContainer.java @@ -237,6 +237,10 @@ public class QSContainer extends FrameLayout { mQSPanel.setListening(mListening && mQsExpanded); } + public void setHeaderListening(boolean listening) { + mHeader.setListening(listening); + } + public void setQsExpansion(float expansion, float headerTranslation) { if (DEBUG) Log.d(TAG, "setQSExpansion " + expansion + " " + headerTranslation); mQsExpansion = expansion; diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java index b6597a025957..ed0fc1fee12a 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java @@ -251,10 +251,12 @@ public class QSPanel extends LinearLayout implements Tunable, Callback { if (mListening) { refreshAllTiles(); } - if (listening) { - mBrightnessController.registerCallbacks(); - } else { - mBrightnessController.unregisterCallbacks(); + if (mBrightnessView.getVisibility() == View.VISIBLE) { + if (listening) { + mBrightnessController.registerCallbacks(); + } else { + mBrightnessController.unregisterCallbacks(); + } } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenWallpaper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenWallpaper.java index 4638c8558ff7..1343c3ad0307 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenWallpaper.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenWallpaper.java @@ -26,6 +26,7 @@ import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Rect; +import android.graphics.Xfermode; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.graphics.drawable.DrawableWrapper; @@ -224,6 +225,12 @@ public class LockscreenWallpaper extends IWallpaperManagerCallback.Stub implemen } @Override + public void setXfermode(@Nullable Xfermode mode) { + // DrawableWrapper does not call this for us. + getDrawable().setXfermode(mode); + } + + @Override public int getIntrinsicWidth() { return -1; } 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 f27f8f53ad8d..812c5c151ce9 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java @@ -1617,6 +1617,9 @@ public class NotificationPanelView extends PanelView implements if (mQsExpanded) { onQsExpansionStarted(); } + // Since there are QS tiles in the header now, we need to make sure we start listening + // immediately so they can be up to date. + mQsContainer.setHeaderListening(true); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java index c9cde9d89f32..047085d20772 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java +++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java @@ -501,7 +501,7 @@ public class VolumeDialog implements TunerService.Tunable { mMotion.startDismiss(new Runnable() { @Override public void run() { - updateExpandedH(false); + updateExpandedH(false /* expanding */, true /* dismissing */); } }); if (mAccessibilityMgr.isEnabled()) { @@ -547,45 +547,47 @@ public class VolumeDialog implements TunerService.Tunable { mHandler.sendEmptyMessageDelayed(H.UPDATE_BOTTOM_MARGIN, getConservativeCollapseDuration()); } - private void updateExpandedH(final boolean expanded) { + private void updateExpandedH(final boolean expanded, final boolean dismissing) { if (mExpanded == expanded) return; mExpanded = expanded; mExpandButtonAnimationRunning = isAttached(); if (D.BUG) Log.d(TAG, "updateExpandedH " + expanded); updateExpandButtonH(); updateFooterH(); + TransitionManager.endTransitions(mDialogView); final VolumeRow activeRow = getActiveRow(); - mWindow.setLayout(mWindow.getAttributes().width, ViewGroup.LayoutParams.MATCH_PARENT); - AutoTransition transition = new AutoTransition(); - transition.setDuration(mExpandButtonAnimationDuration); - transition.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN); - transition.addListener(new Transition.TransitionListener() { - @Override - public void onTransitionStart(Transition transition) { - } + if (!dismissing) { + mWindow.setLayout(mWindow.getAttributes().width, ViewGroup.LayoutParams.MATCH_PARENT); + AutoTransition transition = new AutoTransition(); + transition.setDuration(mExpandButtonAnimationDuration); + transition.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN); + transition.addListener(new Transition.TransitionListener() { + @Override + public void onTransitionStart(Transition transition) { + } - @Override - public void onTransitionEnd(Transition transition) { - mWindow.setLayout( - mWindow.getAttributes().width, ViewGroup.LayoutParams.WRAP_CONTENT); - } + @Override + public void onTransitionEnd(Transition transition) { + mWindow.setLayout( + mWindow.getAttributes().width, ViewGroup.LayoutParams.WRAP_CONTENT); + } - @Override - public void onTransitionCancel(Transition transition) { - mWindow.setLayout( - mWindow.getAttributes().width, ViewGroup.LayoutParams.WRAP_CONTENT); - } + @Override + public void onTransitionCancel(Transition transition) { + } - @Override - public void onTransitionPause(Transition transition) { - } + @Override + public void onTransitionPause(Transition transition) { + mWindow.setLayout( + mWindow.getAttributes().width, ViewGroup.LayoutParams.WRAP_CONTENT); + } - @Override - public void onTransitionResume(Transition transition) { - } - }); - TransitionManager.endTransitions(mDialogView); - TransitionManager.beginDelayedTransition(mDialogView, transition); + @Override + public void onTransitionResume(Transition transition) { + } + }); + TransitionManager.beginDelayedTransition(mDialogView, transition); + } updateRowsH(activeRow); rescheduleTimeoutH(); } @@ -1035,7 +1037,7 @@ public class VolumeDialog implements TunerService.Tunable { if (mExpandButtonAnimationRunning) return; final boolean newExpand = !mExpanded; Events.writeEvent(mContext, Events.EVENT_EXPAND, newExpand); - updateExpandedH(newExpand); + updateExpandedH(newExpand, false /* dismissing */); } }; diff --git a/packages/WallpaperBackup/src/com/android/wallpaperbackup/WallpaperBackupAgent.java b/packages/WallpaperBackup/src/com/android/wallpaperbackup/WallpaperBackupAgent.java index 82b305087707..242eca8898ce 100644 --- a/packages/WallpaperBackup/src/com/android/wallpaperbackup/WallpaperBackupAgent.java +++ b/packages/WallpaperBackup/src/com/android/wallpaperbackup/WallpaperBackupAgent.java @@ -34,6 +34,8 @@ import android.os.UserHandle; import android.util.Slog; import android.util.Xml; +import libcore.io.IoUtils; + import org.xmlpull.v1.XmlPullParser; import java.io.File; @@ -112,56 +114,58 @@ public class WallpaperBackupAgent extends BackupAgent { touch.close(); fullBackupFile(empty, data); - // only back up the wallpaper if we've been told it's allowed - if (mWm.isWallpaperBackupEligible()) { - if (DEBUG) { - Slog.v(TAG, "Wallpaper is backup-eligible"); - } + SharedPreferences prefs = getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE); + final int lastSysGeneration = prefs.getInt(SYSTEM_GENERATION, -1); + final int lastLockGeneration = prefs.getInt(LOCK_GENERATION, -1); - SharedPreferences prefs = getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE); - final int lastSysGeneration = prefs.getInt(SYSTEM_GENERATION, -1); - final int lastLockGeneration = prefs.getInt(LOCK_GENERATION, -1); + final int sysGeneration = + mWm.getWallpaperIdForUser(FLAG_SYSTEM, UserHandle.USER_SYSTEM); + final int lockGeneration = + mWm.getWallpaperIdForUser(FLAG_LOCK, UserHandle.USER_SYSTEM); + final boolean sysChanged = (sysGeneration != lastSysGeneration); + final boolean lockChanged = (lockGeneration != lastLockGeneration); - final int sysGeneration = - mWm.getWallpaperIdForUser(FLAG_SYSTEM, UserHandle.USER_SYSTEM); - final int lockGeneration = - mWm.getWallpaperIdForUser(FLAG_LOCK, UserHandle.USER_SYSTEM); - final boolean sysChanged = (sysGeneration != lastSysGeneration); - final boolean lockChanged = (lockGeneration != lastLockGeneration); + final boolean sysEligible = mWm.isWallpaperBackupEligible(FLAG_SYSTEM); + final boolean lockEligible = mWm.isWallpaperBackupEligible(FLAG_LOCK); - if (DEBUG) { - Slog.v(TAG, "sysGen=" + sysGeneration + " : sysChanged=" + sysChanged); - Slog.v(TAG, "lockGen=" + lockGeneration + " : lockChanged=" + lockChanged); - } - if (mWallpaperInfo.exists()) { - if (sysChanged || lockChanged || !infoStage.exists()) { - if (DEBUG) Slog.v(TAG, "New wallpaper configuration; copying"); - FileUtils.copyFileOrThrow(mWallpaperInfo, infoStage); - } - fullBackupFile(infoStage, data); + // There might be a latent lock wallpaper file present but unused: don't + // include it in the backup if that's the case. + ParcelFileDescriptor lockFd = mWm.getWallpaperFile(FLAG_LOCK, UserHandle.USER_SYSTEM); + final boolean hasLockWallpaper = (lockFd != null); + IoUtils.closeQuietly(lockFd); + + if (DEBUG) { + Slog.v(TAG, "sysGen=" + sysGeneration + " : sysChanged=" + sysChanged); + Slog.v(TAG, "lockGen=" + lockGeneration + " : lockChanged=" + lockChanged); + Slog.v(TAG, "sysEligble=" + sysEligible); + Slog.v(TAG, "lockEligible=" + lockEligible); + } + + // only back up the wallpapers if we've been told they're eligible + if ((sysEligible || lockEligible) && mWallpaperInfo.exists()) { + if (sysChanged || lockChanged || !infoStage.exists()) { + if (DEBUG) Slog.v(TAG, "New wallpaper configuration; copying"); + FileUtils.copyFileOrThrow(mWallpaperInfo, infoStage); } - if (mWallpaperFile.exists()) { - if (sysChanged || !imageStage.exists()) { - if (DEBUG) Slog.v(TAG, "New system wallpaper; copying"); - FileUtils.copyFileOrThrow(mWallpaperFile, imageStage); - } - fullBackupFile(imageStage, data); - prefs.edit().putInt(SYSTEM_GENERATION, sysGeneration).apply(); + fullBackupFile(infoStage, data); + } + if (sysEligible && mWallpaperFile.exists()) { + if (sysChanged || !imageStage.exists()) { + if (DEBUG) Slog.v(TAG, "New system wallpaper; copying"); + FileUtils.copyFileOrThrow(mWallpaperFile, imageStage); } + fullBackupFile(imageStage, data); + prefs.edit().putInt(SYSTEM_GENERATION, sysGeneration).apply(); + } - // Don't try to store the lock image if we overran our quota last time - if (mLockWallpaperFile.exists() && !mQuotaExceeded) { - if (lockChanged || !lockImageStage.exists()) { - if (DEBUG) Slog.v(TAG, "New lock wallpaper; copying"); - FileUtils.copyFileOrThrow(mLockWallpaperFile, lockImageStage); - } - fullBackupFile(lockImageStage, data); - prefs.edit().putInt(LOCK_GENERATION, lockGeneration).apply(); - } - } else { - if (DEBUG) { - Slog.v(TAG, "Wallpaper not backup-eligible; writing no data"); + // Don't try to store the lock image if we overran our quota last time + if (lockEligible && hasLockWallpaper && mLockWallpaperFile.exists() && !mQuotaExceeded) { + if (lockChanged || !lockImageStage.exists()) { + if (DEBUG) Slog.v(TAG, "New lock wallpaper; copying"); + FileUtils.copyFileOrThrow(mLockWallpaperFile, lockImageStage); } + fullBackupFile(lockImageStage, data); + prefs.edit().putInt(LOCK_GENERATION, lockGeneration).apply(); } } catch (Exception e) { Slog.e(TAG, "Unable to back up wallpaper", e); @@ -199,15 +203,20 @@ public class WallpaperBackupAgent extends BackupAgent { final File imageStage = new File (filesDir, IMAGE_STAGE); final File lockImageStage = new File (filesDir, LOCK_IMAGE_STAGE); + // If we restored separate lock imagery, the system wallpaper should be + // applied as system-only; but if there's no separate lock image, make + // sure to apply the restored system wallpaper as both. + final int sysWhich = FLAG_SYSTEM | (lockImageStage.exists() ? 0 : FLAG_LOCK); + try { // First off, revert to the factory state - mWm.clear(WallpaperManager.FLAG_SYSTEM | WallpaperManager.FLAG_LOCK); + mWm.clear(FLAG_SYSTEM | FLAG_LOCK); // It is valid for the imagery to be absent; it means that we were not permitted // to back up the original image on the source device, or there was no user-supplied // wallpaper image present. - restoreFromStage(imageStage, infoStage, "wp", WallpaperManager.FLAG_SYSTEM); - restoreFromStage(lockImageStage, infoStage, "kwp", WallpaperManager.FLAG_LOCK); + restoreFromStage(imageStage, infoStage, "wp", sysWhich); + restoreFromStage(lockImageStage, infoStage, "kwp", FLAG_LOCK); } catch (Exception e) { Slog.e(TAG, "Unable to restore wallpaper: " + e.getMessage()); } finally { diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java index 983a6566f4d9..ea25f7438d79 100644 --- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java +++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java @@ -21,6 +21,7 @@ import static android.accessibilityservice.AccessibilityServiceInfo.DEFAULT; import android.Manifest; import android.accessibilityservice.AccessibilityService; import android.accessibilityservice.AccessibilityServiceInfo; +import android.accessibilityservice.GestureDescription; import android.accessibilityservice.IAccessibilityServiceClient; import android.accessibilityservice.IAccessibilityServiceConnection; import android.annotation.NonNull; @@ -2787,7 +2788,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { } @Override - public void sendMotionEvents(int sequence, ParceledListSlice events) { + public void sendGesture(int sequence, ParceledListSlice gestureSteps) { synchronized (mLock) { if (mSecurityPolicy.canPerformGestures(this)) { final long endMillis = @@ -2801,9 +2802,16 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { } } if (mMotionEventInjector != null) { - mMotionEventInjector.injectEvents((List<MotionEvent>) events.getList(), - mServiceInterface, sequence); - return; + List<GestureDescription.GestureStep> steps = gestureSteps.getList(); + List<MotionEvent> events = GestureDescription.MotionEventGenerator + .getMotionEventsFromGestureSteps(steps); + // Confirm that the motion events end with an UP event. + if (events.get(events.size() - 1).getAction() == MotionEvent.ACTION_UP) { + mMotionEventInjector.injectEvents(events, mServiceInterface, sequence); + return; + } else { + Slog.e(LOG_TAG, "Gesture is not well-formed"); + } } else { Slog.e(LOG_TAG, "MotionEventInjector installation timed out"); } diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetService.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetService.java index 915d839d530a..9cc53f02de1c 100644 --- a/services/appwidget/java/com/android/server/appwidget/AppWidgetService.java +++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetService.java @@ -34,6 +34,7 @@ public class AppWidgetService extends SystemService { @Override public void onStart() { + mImpl.onStart(); publishBinderService(Context.APPWIDGET_SERVICE, mImpl); AppWidgetBackupBridge.register(mImpl); } diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java index 47094be808cf..5ec3f2b565b6 100644 --- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java +++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java @@ -201,21 +201,21 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku private final SparseArray<ArraySet<String>> mWidgetPackages = new SparseArray<>(); - private final BackupRestoreController mBackupRestoreController; + private BackupRestoreController mBackupRestoreController; private final Context mContext; - private final IPackageManager mPackageManager; - private final AlarmManager mAlarmManager; - private final UserManager mUserManager; - private final AppOpsManager mAppOpsManager; - private final KeyguardManager mKeyguardManager; - private final DevicePolicyManagerInternal mDevicePolicyManagerInternal; + private IPackageManager mPackageManager; + private AlarmManager mAlarmManager; + private UserManager mUserManager; + private AppOpsManager mAppOpsManager; + private KeyguardManager mKeyguardManager; + private DevicePolicyManagerInternal mDevicePolicyManagerInternal; - private final SecurityPolicy mSecurityPolicy; + private SecurityPolicy mSecurityPolicy; - private final Handler mSaveStateHandler; - private final Handler mCallbackHandler; + private Handler mSaveStateHandler; + private Handler mCallbackHandler; private Locale mLocale; @@ -224,10 +224,13 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku private boolean mSafeMode; private int mMaxWidgetBitmapMemory; - private final IconUtilities mIconUtilities; + private IconUtilities mIconUtilities; AppWidgetServiceImpl(Context context) { mContext = context; + } + + public void onStart() { mPackageManager = AppGlobals.getPackageManager(); mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE); mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE); @@ -238,7 +241,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku mCallbackHandler = new CallbackHandler(mContext.getMainLooper()); mBackupRestoreController = new BackupRestoreController(); mSecurityPolicy = new SecurityPolicy(); - mIconUtilities = new IconUtilities(context); + mIconUtilities = new IconUtilities(mContext); computeMaximumWidgetBitmapMemory(); registerBroadcastReceiver(); diff --git a/services/core/java/com/android/server/AlarmManagerService.java b/services/core/java/com/android/server/AlarmManagerService.java index 03160932063c..20cca16991c9 100644 --- a/services/core/java/com/android/server/AlarmManagerService.java +++ b/services/core/java/com/android/server/AlarmManagerService.java @@ -2699,7 +2699,7 @@ class AlarmManagerService extends SystemService { public void scheduleDateChangedEvent() { Calendar calendar = Calendar.getInstance(); calendar.setTimeInMillis(System.currentTimeMillis()); - calendar.set(Calendar.HOUR, 0); + calendar.set(Calendar.HOUR_OF_DAY, 0); calendar.set(Calendar.MINUTE, 0); calendar.set(Calendar.SECOND, 0); calendar.set(Calendar.MILLISECOND, 0); diff --git a/services/core/java/com/android/server/DeviceIdleController.java b/services/core/java/com/android/server/DeviceIdleController.java index 488f0e793c9a..6b73fec8c920 100644 --- a/services/core/java/com/android/server/DeviceIdleController.java +++ b/services/core/java/com/android/server/DeviceIdleController.java @@ -49,7 +49,6 @@ import android.os.Bundle; import android.os.Environment; import android.os.FileUtils; import android.os.Handler; -import android.os.IBinder; import android.os.IDeviceIdleController; import android.os.IMaintenanceActivityListener; import android.os.Looper; @@ -1238,7 +1237,7 @@ public class DeviceIdleController extends SystemService } } - public final class LocalService { + public class LocalService { public void addPowerSaveTempWhitelistAppDirect(int appId, long duration, boolean sync, String reason) { addPowerSaveTempWhitelistAppDirectInternal(0, appId, duration, sync, reason); diff --git a/services/core/java/com/android/server/LockSettingsService.java b/services/core/java/com/android/server/LockSettingsService.java index 2de09a39f6ab..801a436e8d80 100644 --- a/services/core/java/com/android/server/LockSettingsService.java +++ b/services/core/java/com/android/server/LockSettingsService.java @@ -52,6 +52,7 @@ import android.os.RemoteException; import android.os.storage.IMountService; import android.os.storage.StorageManager; import android.os.ServiceManager; +import android.os.StrictMode; import android.os.SystemProperties; import android.os.UserHandle; import android.os.UserManager; @@ -1367,6 +1368,10 @@ public class LockSettingsService extends ILockSettings.Stub { return VerifyCredentialResponse.ERROR; } + // We're potentially going to be doing a bunch of disk I/O below as part + // of unlocking the user, so yell if calling from the main thread. + StrictMode.noteDiskRead(); + if (storedHash.version == CredentialHash.VERSION_LEGACY) { byte[] hash = credentialUtil.toHash(credential, userId); if (Arrays.equals(hash, storedHash.hash)) { diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 0ffc35b6a5f0..09a3a172c79f 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -2341,7 +2341,7 @@ public final class ActivityManagerService extends ActivityManagerNative Process.SCHED_OTHER, 0); } } catch (IllegalArgumentException e) { - Slog.e(TAG, "Failed to set scheduling policy, thread does" + Slog.w(TAG, "Failed to set scheduling policy, thread does" + " not exist:\n" + e); } } @@ -3807,6 +3807,15 @@ public final class ActivityManagerService extends ActivityManagerNative app.killedByAm = false; checkTime(startTime, "startProcess: starting to update pids map"); synchronized (mPidsSelfLocked) { + ProcessRecord oldApp; + // If there is already an app occupying that pid that hasn't been cleaned up + if ((oldApp = mPidsSelfLocked.get(startResult.pid)) != null && !app.isolated) { + // Clean up anything relating to this pid first + Slog.w(TAG, "Reusing pid " + startResult.pid + + " while app is still mapped to it"); + cleanUpApplicationRecordLocked(oldApp, false, false, -1, + true /*replacingPid*/); + } this.mPidsSelfLocked.put(startResult.pid, app); if (isActivityProcess) { Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG); @@ -5039,7 +5048,8 @@ public final class ActivityManagerService extends ActivityManagerNative private final void handleAppDiedLocked(ProcessRecord app, boolean restarting, boolean allowRestart) { int pid = app.pid; - boolean kept = cleanUpApplicationRecordLocked(app, restarting, allowRestart, -1); + boolean kept = cleanUpApplicationRecordLocked(app, restarting, allowRestart, -1, + false /*replacingPid*/); if (!kept && !restarting) { removeLruProcessLocked(app); if (pid > 0) { @@ -12572,10 +12582,15 @@ public final class ActivityManagerService extends ActivityManagerNative proc.vrThreadTid = tid; // promote to FIFO now if the tid is non-zero - if (proc.curSchedGroup == ProcessList.SCHED_GROUP_TOP_APP - && proc.vrThreadTid > 0) { - Process.setThreadScheduler(proc.vrThreadTid, + try { + if (proc.curSchedGroup == ProcessList.SCHED_GROUP_TOP_APP && + proc.vrThreadTid > 0) { + Process.setThreadScheduler(proc.vrThreadTid, Process.SCHED_FIFO | Process.SCHED_RESET_ON_FORK, 1); + } + } catch (IllegalArgumentException e) { + Slog.e(TAG, "Failed to set scheduling policy, thread does" + + " not exist:\n" + e); } } } @@ -16811,7 +16826,8 @@ public final class ActivityManagerService extends ActivityManagerNative * app that was passed in must remain on the process lists. */ private final boolean cleanUpApplicationRecordLocked(ProcessRecord app, - boolean restarting, boolean allowRestart, int index) { + boolean restarting, boolean allowRestart, int index, boolean replacingPid) { + Slog.d(TAG, "cleanUpApplicationRecord -- " + app.pid); if (index >= 0) { removeLruProcessLocked(app); ProcessList.remove(app.pid); @@ -16942,7 +16958,9 @@ public final class ActivityManagerService extends ActivityManagerNative if (!app.persistent || app.isolated) { if (DEBUG_PROCESSES || DEBUG_CLEANUP) Slog.v(TAG_CLEANUP, "Removing non-persistent process during cleanup: " + app); - removeProcessNameLocked(app.processName, app.uid); + if (!replacingPid) { + removeProcessNameLocked(app.processName, app.uid); + } if (mHeavyWeightProcess == app) { mHandler.sendMessage(mHandler.obtainMessage(CANCEL_HEAVY_NOTIFICATION_MSG, mHeavyWeightProcess.userId, 0)); @@ -20350,17 +20368,29 @@ public final class ActivityManagerService extends ActivityManagerNative if (oldSchedGroup != ProcessList.SCHED_GROUP_TOP_APP) { // Switch VR thread for app to SCHED_FIFO if (mInVrMode && app.vrThreadTid != 0) { - Process.setThreadScheduler(app.vrThreadTid, - Process.SCHED_FIFO | Process.SCHED_RESET_ON_FORK, 1); + try { + Process.setThreadScheduler(app.vrThreadTid, + Process.SCHED_FIFO | Process.SCHED_RESET_ON_FORK, 1); + } catch (IllegalArgumentException e) { + // thread died, ignore + } } if (mUseFifoUiScheduling) { // Switch UI pipeline for app to SCHED_FIFO app.savedPriority = Process.getThreadPriority(app.pid); - Process.setThreadScheduler(app.pid, - Process.SCHED_FIFO | Process.SCHED_RESET_ON_FORK, 1); - if (app.renderThreadTid != 0) { - Process.setThreadScheduler(app.renderThreadTid, + try { + Process.setThreadScheduler(app.pid, Process.SCHED_FIFO | Process.SCHED_RESET_ON_FORK, 1); + } catch (IllegalArgumentException e) { + // thread died, ignore + } + if (app.renderThreadTid != 0) { + try { + Process.setThreadScheduler(app.renderThreadTid, + Process.SCHED_FIFO | Process.SCHED_RESET_ON_FORK, 1); + } catch (IllegalArgumentException e) { + // thread died, ignore + } if (DEBUG_OOM_ADJ) { Slog.d("UI_FIFO", "Set RenderThread (TID " + app.renderThreadTid + ") to FIFO"); @@ -20374,7 +20404,11 @@ public final class ActivityManagerService extends ActivityManagerNative // Boost priority for top app UI and render threads Process.setThreadPriority(app.pid, -10); if (app.renderThreadTid != 0) { - Process.setThreadPriority(app.renderThreadTid, -10); + try { + Process.setThreadPriority(app.renderThreadTid, -10); + } catch (IllegalArgumentException e) { + // thread died, ignore + } } } } @@ -21258,7 +21292,7 @@ public final class ActivityManagerService extends ActivityManagerNative // Ignore exceptions. } } - cleanUpApplicationRecordLocked(app, false, true, -1); + cleanUpApplicationRecordLocked(app, false, true, -1, false /*replacingPid*/); mRemovedProcesses.remove(i); if (app.persistent) { diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java index d02fbbfa9ac9..219e0958a8fe 100644 --- a/services/core/java/com/android/server/am/BroadcastQueue.java +++ b/services/core/java/com/android/server/am/BroadcastQueue.java @@ -304,6 +304,11 @@ public final class BroadcastQueue { boolean didSomething = false; final BroadcastRecord br = mPendingBroadcast; if (br != null && br.curApp.pid == app.pid) { + if (br.curApp != app) { + Slog.e(TAG, "App mismatch when sending pending broadcast to " + + app.processName + ", intended target is " + br.curApp.processName); + return false; + } try { mPendingBroadcast = null; processCurBroadcastLocked(br, app); diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java index 64dea571f014..75878476f753 100644 --- a/services/core/java/com/android/server/audio/AudioService.java +++ b/services/core/java/com/android/server/audio/AudioService.java @@ -746,9 +746,8 @@ public class AudioService extends IAudioService.Stub { BluetoothProfile.A2DP); } - mHdmiManager = - (HdmiControlManager) mContext.getSystemService(Context.HDMI_CONTROL_SERVICE); - if (mHdmiManager != null) { + if (mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_HDMI_CEC)) { + mHdmiManager = mContext.getSystemService(HdmiControlManager.class); synchronized (mHdmiManager) { mHdmiTvClient = mHdmiManager.getTvClient(); if (mHdmiTvClient != null) { diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java index 61af8edebb83..d6cc9fc6a85c 100644 --- a/services/core/java/com/android/server/display/DisplayPowerController.java +++ b/services/core/java/com/android/server/display/DisplayPowerController.java @@ -102,9 +102,6 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call // Trigger proximity if distance is less than 5 cm. private static final float TYPICAL_PROXIMITY_THRESHOLD = 5.0f; - // Brightness animation ramp rate in brightness units per second. - private static final int BRIGHTNESS_RAMP_RATE_SLOW = 40; - private static final int REPORTED_TO_POLICY_SCREEN_OFF = 0; private static final int REPORTED_TO_POLICY_SCREEN_TURNING_ON = 1; private static final int REPORTED_TO_POLICY_SCREEN_ON = 2; @@ -243,8 +240,9 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call private boolean mAppliedDimming; private boolean mAppliedLowPower; - // Brightness ramp rate fast. + // Brightness animation ramp rates in brightness units per second private final int mBrightnessRampRateFast; + private final int mBrightnessRampRateSlow; // The controller for the automatic brightness level. private AutomaticBrightnessController mAutomaticBrightnessController; @@ -307,6 +305,8 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call mBrightnessRampRateFast = resources.getInteger( com.android.internal.R.integer.config_brightness_ramp_rate_fast); + mBrightnessRampRateSlow = resources.getInteger( + com.android.internal.R.integer.config_brightness_ramp_rate_slow); int lightSensorRate = resources.getInteger( com.android.internal.R.integer.config_autoBrightnessLightSensorRate); @@ -703,7 +703,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call if (!mPendingScreenOff) { if (state == Display.STATE_ON || state == Display.STATE_DOZE) { animateScreenBrightness(brightness, - slowChange ? BRIGHTNESS_RAMP_RATE_SLOW : mBrightnessRampRateFast); + slowChange ? mBrightnessRampRateSlow : mBrightnessRampRateFast); } else { animateScreenBrightness(brightness, 0); } diff --git a/services/core/java/com/android/server/display/NightDisplayService.java b/services/core/java/com/android/server/display/NightDisplayService.java index d9af7cb913ee..07fa2ce01b3b 100644 --- a/services/core/java/com/android/server/display/NightDisplayService.java +++ b/services/core/java/com/android/server/display/NightDisplayService.java @@ -20,6 +20,7 @@ import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.TypeEvaluator; import android.animation.ValueAnimator; +import android.annotation.NonNull; import android.annotation.Nullable; import android.app.AlarmManager; import android.content.BroadcastReceiver; @@ -361,13 +362,12 @@ public final class NightDisplayService extends SystemService if (setActivated) { mController.setActivated(activated); } - updateNextAlarm(); + updateNextAlarm(mIsActivated, now); } - private void updateNextAlarm() { - if (mIsActivated != null) { - final Calendar now = Calendar.getInstance(); - final Calendar next = mIsActivated ? mEndTime.getDateTimeAfter(now) + private void updateNextAlarm(@Nullable Boolean activated, @NonNull Calendar now) { + if (activated != null) { + final Calendar next = activated ? mEndTime.getDateTimeAfter(now) : mStartTime.getDateTimeAfter(now); mAlarmManager.setExact(AlarmManager.RTC, next.getTimeInMillis(), TAG, this, null); } @@ -396,10 +396,11 @@ public final class NightDisplayService extends SystemService @Override public void onActivated(boolean activated) { + final Calendar now = Calendar.getInstance(); if (mIsActivated != null) { - mLastActivatedTime = Calendar.getInstance(); + mLastActivatedTime = now; } - updateNextAlarm(); + updateNextAlarm(activated, now); } @Override diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java index d8e5f637f0ba..9ca609f8468a 100644 --- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java +++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java @@ -133,7 +133,6 @@ import android.os.Handler; import android.os.HandlerThread; import android.os.IDeviceIdleController; import android.os.INetworkManagementService; -import android.os.IPowerManager; import android.os.Message; import android.os.MessageQueue.IdleHandler; import android.os.PowerManager; @@ -287,7 +286,6 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { private static final int MSG_LIMIT_REACHED = 5; private static final int MSG_RESTRICT_BACKGROUND_CHANGED = 6; private static final int MSG_ADVISE_PERSIST_THRESHOLD = 7; - private static final int MSG_SCREEN_ON_CHANGED = 8; private static final int MSG_RESTRICT_BACKGROUND_WHITELIST_CHANGED = 9; private static final int MSG_UPDATE_INTERFACE_QUOTA = 10; private static final int MSG_REMOVE_INTERFACE_QUOTA = 11; @@ -295,7 +293,6 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { private final Context mContext; private final IActivityManager mActivityManager; - private final IPowerManager mPowerManager; private final INetworkStatsService mNetworkStats; private final INetworkManagementService mNetworkManager; private UsageStatsManagerInternal mUsageStats; @@ -313,7 +310,6 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { @GuardedBy("allLocks") volatile boolean mSystemReady; - @GuardedBy("mUidRulesFirstLock") volatile boolean mScreenOn; @GuardedBy("mUidRulesFirstLock") volatile boolean mRestrictBackground; @GuardedBy("mUidRulesFirstLock") volatile boolean mRestrictPower; @GuardedBy("mUidRulesFirstLock") volatile boolean mDeviceIdleMode; @@ -419,9 +415,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { // TODO: migrate notifications to SystemUI public NetworkPolicyManagerService(Context context, IActivityManager activityManager, - IPowerManager powerManager, INetworkStatsService networkStats, - INetworkManagementService networkManagement) { - this(context, activityManager, powerManager, networkStats, networkManagement, + INetworkStatsService networkStats, INetworkManagementService networkManagement) { + this(context, activityManager, networkStats, networkManagement, NtpTrustedTime.getInstance(context), getSystemDir(), false); } @@ -430,12 +425,10 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } public NetworkPolicyManagerService(Context context, IActivityManager activityManager, - IPowerManager powerManager, INetworkStatsService networkStats, - INetworkManagementService networkManagement, TrustedTime time, File systemDir, - boolean suppressDefaultPolicy) { + INetworkStatsService networkStats, INetworkManagementService networkManagement, + TrustedTime time, File systemDir, boolean suppressDefaultPolicy) { mContext = checkNotNull(context, "missing context"); mActivityManager = checkNotNull(activityManager, "missing activityManager"); - mPowerManager = checkNotNull(powerManager, "missing powerManager"); mNetworkStats = checkNotNull(networkStats, "missing networkStats"); mNetworkManager = checkNotNull(networkManagement, "missing networkManagement"); mDeviceIdleController = IDeviceIdleController.Stub.asInterface(ServiceManager.getService( @@ -619,8 +612,6 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } } - updateScreenOn(); - try { mActivityManager.registerUidObserver(mUidObserver, ActivityManager.UID_OBSERVER_PROCSTATE|ActivityManager.UID_OBSERVER_GONE); @@ -629,14 +620,6 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { // ignored; both services live in system_server } - // TODO: traverse existing processes to know foreground state, or have - // activitymanager dispatch current state when new observer attached. - - final IntentFilter screenFilter = new IntentFilter(); - screenFilter.addAction(Intent.ACTION_SCREEN_ON); - screenFilter.addAction(Intent.ACTION_SCREEN_OFF); - mContext.registerReceiver(mScreenReceiver, screenFilter); - // listen for changes to power save whitelist final IntentFilter whitelistFilter = new IntentFilter( PowerManager.ACTION_POWER_SAVE_WHITELIST_CHANGED); @@ -735,15 +718,6 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } }; - final private BroadcastReceiver mScreenReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - // screen-related broadcasts are protected by system, no need - // for permissions check. - mHandler.obtainMessage(MSG_SCREEN_ON_CHANGED).sendToTarget(); - } - }; - final private BroadcastReceiver mPackageReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { @@ -1076,6 +1050,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { builder.setTicker(title); builder.setContentTitle(title); builder.setContentText(body); + builder.setDefaults(Notification.DEFAULT_ALL); + builder.setPriority(Notification.PRIORITY_HIGH); final Intent snoozeIntent = buildSnoozeWarningIntent(policy.template); builder.setDeleteIntent(PendingIntent.getBroadcast( @@ -2524,7 +2500,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { private boolean isUidStateForegroundUL(int state) { // only really in foreground when screen is also on - return mScreenOn && state <= ActivityManager.PROCESS_STATE_TOP; + return state <= ActivityManager.PROCESS_STATE_TOP; } /** @@ -2595,31 +2571,6 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } } - private void updateScreenOn() { - synchronized (mUidRulesFirstLock) { - try { - mScreenOn = mPowerManager.isInteractive(); - } catch (RemoteException e) { - // ignored; service lives in system_server - } - updateRulesForScreenUL(); - } - } - - /** - * Update rules that might be changed by {@link #mScreenOn} value. - */ - private void updateRulesForScreenUL() { - // only update rules for anyone with foreground activities - final int size = mUidState.size(); - for (int i = 0; i < size; i++) { - if (mUidState.valueAt(i) <= ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE) { - final int uid = mUidState.keyAt(i); - updateRestrictionRulesForUidUL(uid); - } - } - } - static boolean isProcStateAllowedWhileIdleOrPowerSaveMode(int procState) { return procState <= ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE; } @@ -3001,12 +2952,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { mUidRules.put(uid, newUidRules); } - boolean changed = false; - // Second step: apply bw changes based on change of state. if (newRule != oldRule) { - changed = true; - if ((newRule & RULE_TEMPORARY_ALLOW_METERED) != 0) { // Temporarily whitelist foreground app, removing from blacklist if necessary // (since bw_penalty_box prevails over bw_happy_box). @@ -3086,7 +3033,6 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { final boolean isIdle = isUidIdle(uid); final boolean restrictMode = isIdle || mRestrictPower || mDeviceIdleMode; - final int uidPolicy = mUidPolicy.get(uid, POLICY_NONE); final int oldUidRules = mUidRules.get(uid, RULE_NONE); final boolean isForeground = isUidForegroundOnRestrictPowerUL(uid); @@ -3109,7 +3055,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { final int newUidRules = (oldUidRules & MASK_METERED_NETWORKS) | newRule; if (LOGV) { - Log.v(TAG, "updateRulesForNonMeteredNetworksUL(" + uid + ")" + Log.v(TAG, "updateRulesForPowerRestrictionsUL(" + uid + ")" + ", isIdle: " + isIdle + ", mRestrictPower: " + mRestrictPower + ", mDeviceIdleMode: " + mDeviceIdleMode @@ -3351,10 +3297,6 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } return true; } - case MSG_SCREEN_ON_CHANGED: { - updateScreenOn(); - return true; - } case MSG_UPDATE_INTERFACE_QUOTA: { removeInterfaceQuota((String) msg.obj); // int params need to be stitched back into a long diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 4994d6bc9206..ab83c11bd8e6 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -364,6 +364,7 @@ public class PackageManagerService extends IPackageManager.Stub { private static final boolean DEBUG_TRIAGED_MISSING = false; private static final boolean DEBUG_APP_DATA = false; + /** REMOVE. According to Svet, this was only used to reset permissions during development. */ static final boolean CLEAR_RUNTIME_PERMISSIONS_ON_UPGRADE = false; private static final boolean DISABLE_EPHEMERAL_APPS = !Build.IS_DEBUGGABLE; @@ -801,10 +802,9 @@ public class PackageManagerService extends IPackageManager.Stub { PackageParser.ActivityIntentInfo filter = filters.get(m); domainsSet.addAll(filter.getHostsList()); } - ArrayList<String> domainsList = new ArrayList<>(domainsSet); synchronized (mPackages) { if (mSettings.createIntentFilterVerificationIfNeededLPw( - packageName, domainsList) != null) { + packageName, domainsSet) != null) { scheduleWriteSettingsLocked(); } } @@ -2873,7 +2873,6 @@ public class PackageManagerService extends IPackageManager.Stub { SystemConfig systemConfig = SystemConfig.getInstance(); ArraySet<String> packages = systemConfig.getLinkedApps(); - ArraySet<String> domains = new ArraySet<String>(); for (String packageName : packages) { PackageParser.Package pkg = mPackages.get(packageName); @@ -2883,16 +2882,19 @@ public class PackageManagerService extends IPackageManager.Stub { continue; } - domains.clear(); + ArraySet<String> domains = null; for (PackageParser.Activity a : pkg.activities) { for (ActivityIntentInfo filter : a.intents) { if (hasValidDomains(filter)) { + if (domains == null) { + domains = new ArraySet<String>(); + } domains.addAll(filter.getHostsList()); } } } - if (domains.size() > 0) { + if (domains != null && domains.size() > 0) { if (DEBUG_DOMAIN_VERIFICATION) { Slog.v(TAG, " + " + packageName); } @@ -2900,8 +2902,7 @@ public class PackageManagerService extends IPackageManager.Stub { // state w.r.t. the formal app-linkage "no verification attempted" state; // and then 'always' in the per-user state actually used for intent resolution. final IntentFilterVerificationInfo ivi; - ivi = mSettings.createIntentFilterVerificationIfNeededLPw(packageName, - new ArrayList<String>(domains)); + ivi = mSettings.createIntentFilterVerificationIfNeededLPw(packageName, domains); ivi.setStatus(INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED); mSettings.updateIntentFilterVerificationStatusLPw(packageName, INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS, userId); @@ -8164,12 +8165,12 @@ public class PackageManagerService extends IPackageManager.Stub { // Just create the setting, don't add it yet. For already existing packages // the PkgSetting exists already and doesn't have to be created. - pkgSetting = mSettings.getPackageLPw(pkg, origPackage, realName, suid, destCodeFile, - destResourceFile, pkg.applicationInfo.nativeLibraryRootDir, + pkgSetting = mSettings.getPackageWithBenefitsLPw(pkg, origPackage, realName, suid, + destCodeFile, destResourceFile, pkg.applicationInfo.nativeLibraryRootDir, pkg.applicationInfo.primaryCpuAbi, pkg.applicationInfo.secondaryCpuAbi, pkg.applicationInfo.flags, pkg.applicationInfo.privateFlags, - user, false); + user); if (pkgSetting == null) { throw new PackageManagerException(INSTALL_FAILED_INSUFFICIENT_STORAGE, "Creating application package " + pkg.packageName + " failed"); diff --git a/services/core/java/com/android/server/pm/PackageSetting.java b/services/core/java/com/android/server/pm/PackageSetting.java index e3866dfada26..a4604a65634c 100644 --- a/services/core/java/com/android/server/pm/PackageSetting.java +++ b/services/core/java/com/android/server/pm/PackageSetting.java @@ -30,15 +30,23 @@ final class PackageSetting extends PackageSettingBase { int appId; PackageParser.Package pkg; SharedUserSetting sharedUser; + /** + * Temporary holding space for the shared user ID. While parsing package settings, the + * shared users tag may be after the packages. In this case, we must delay linking the + * shared user setting with the package setting. The shared user ID lets us link the + * two objects. + */ + private int sharedUserId; PackageSetting(String name, String realName, File codePath, File resourcePath, String legacyNativeLibraryPathString, String primaryCpuAbiString, String secondaryCpuAbiString, String cpuAbiOverrideString, int pVersionCode, int pkgFlags, int privateFlags, String parentPackageName, - List<String> childPackageNames) { + List<String> childPackageNames, int sharedUserId) { super(name, realName, codePath, resourcePath, legacyNativeLibraryPathString, primaryCpuAbiString, secondaryCpuAbiString, cpuAbiOverrideString, pVersionCode, pkgFlags, privateFlags, parentPackageName, childPackageNames); + this.sharedUserId = sharedUserId; } /** @@ -47,10 +55,14 @@ final class PackageSetting extends PackageSettingBase { */ PackageSetting(PackageSetting orig) { super(orig); + doCopy(orig); + } - appId = orig.appId; - pkg = orig.pkg; - sharedUser = orig.sharedUser; + public int getSharedUserId() { + if (sharedUser != null) { + return sharedUser.userId; + } + return sharedUserId; } @Override @@ -60,6 +72,18 @@ final class PackageSetting extends PackageSettingBase { + " " + name + "/" + appId + "}"; } + public void copyFrom(PackageSetting orig) { + super.copyFrom(orig); + doCopy(orig); + } + + private void doCopy(PackageSetting orig) { + appId = orig.appId; + pkg = orig.pkg; + sharedUser = orig.sharedUser; + sharedUserId = orig.sharedUserId; + } + public PermissionsState getPermissionsState() { return (sharedUser != null) ? sharedUser.getPermissionsState() diff --git a/services/core/java/com/android/server/pm/PackageSettingBase.java b/services/core/java/com/android/server/pm/PackageSettingBase.java index 14ca72c14584..c08bc5743b57 100644 --- a/services/core/java/com/android/server/pm/PackageSettingBase.java +++ b/services/core/java/com/android/server/pm/PackageSettingBase.java @@ -147,51 +147,12 @@ abstract class PackageSettingBase extends SettingBase { secondaryCpuAbiString, cpuAbiOverrideString, pVersionCode); } - /** - * New instance of PackageSetting with one-level-deep cloning. - */ - @SuppressWarnings("unchecked") + /** New instance of PackageSetting with one-level-deep cloning. */ PackageSettingBase(PackageSettingBase base) { super(base); - name = base.name; realName = base.realName; - codePath = base.codePath; - codePathString = base.codePathString; - resourcePath = base.resourcePath; - resourcePathString = base.resourcePathString; - legacyNativeLibraryPathString = base.legacyNativeLibraryPathString; - primaryCpuAbiString = base.primaryCpuAbiString; - secondaryCpuAbiString = base.secondaryCpuAbiString; - cpuAbiOverrideString = base.cpuAbiOverrideString; - timeStamp = base.timeStamp; - firstInstallTime = base.firstInstallTime; - lastUpdateTime = base.lastUpdateTime; - versionCode = base.versionCode; - - uidError = base.uidError; - - signatures = new PackageSignatures(base.signatures); - - installPermissionsFixed = base.installPermissionsFixed; - userState.clear(); - for (int i=0; i<base.userState.size(); i++) { - userState.put(base.userState.keyAt(i), - new PackageUserState(base.userState.valueAt(i))); - } - installStatus = base.installStatus; - - origPackage = base.origPackage; - - installerPackageName = base.installerPackageName; - isOrphaned = base.isOrphaned; - volumeUuid = base.volumeUuid; - - keySetData = new PackageKeySetData(base.keySetData); - - parentPackageName = base.parentPackageName; - childPackageNames = (base.childPackageNames != null) - ? new ArrayList<>(base.childPackageNames) : null; + doCopy(base); } void init(File codePath, File resourcePath, String legacyNativeLibraryPathString, @@ -237,27 +198,47 @@ abstract class PackageSettingBase extends SettingBase { } /** - * Make a shallow copy of this package settings. + * Makes a shallow copy of the given package settings. + * + * NOTE: For some fields [such as keySetData, signatures, userState, verificationInfo, etc...], + * the original object is copied and a new one is not created. */ - public void copyFrom(PackageSettingBase base) { - mPermissionsState.copyFrom(base.mPermissionsState); - primaryCpuAbiString = base.primaryCpuAbiString; - secondaryCpuAbiString = base.secondaryCpuAbiString; - cpuAbiOverrideString = base.cpuAbiOverrideString; - timeStamp = base.timeStamp; - firstInstallTime = base.firstInstallTime; - lastUpdateTime = base.lastUpdateTime; - signatures = base.signatures; - installPermissionsFixed = base.installPermissionsFixed; + public void copyFrom(PackageSettingBase orig) { + super.copyFrom(orig); + doCopy(orig); + } + + private void doCopy(PackageSettingBase orig) { + childPackageNames = (orig.childPackageNames != null) + ? new ArrayList<>(orig.childPackageNames) : null; + codePath = orig.codePath; + codePathString = orig.codePathString; + cpuAbiOverrideString = orig.cpuAbiOverrideString; + firstInstallTime = orig.firstInstallTime; + installPermissionsFixed = orig.installPermissionsFixed; + installStatus = orig.installStatus; + installerPackageName = orig.installerPackageName; + isOrphaned = orig.isOrphaned; + keySetData = orig.keySetData; + lastUpdateTime = orig.lastUpdateTime; + legacyNativeLibraryPathString = orig.legacyNativeLibraryPathString; + // Intentionally skip oldCodePaths; it's not relevant for copies + origPackage = orig.origPackage; + parentPackageName = orig.parentPackageName; + primaryCpuAbiString = orig.primaryCpuAbiString; + resourcePath = orig.resourcePath; + resourcePathString = orig.resourcePathString; + secondaryCpuAbiString = orig.secondaryCpuAbiString; + signatures = orig.signatures; + timeStamp = orig.timeStamp; + uidError = orig.uidError; userState.clear(); - for (int i=0; i<base.userState.size(); i++) { - userState.put(base.userState.keyAt(i), base.userState.valueAt(i)); + for (int i=0; i<orig.userState.size(); i++) { + userState.put(orig.userState.keyAt(i), orig.userState.valueAt(i)); } - installStatus = base.installStatus; - keySetData = base.keySetData; - verificationInfo = base.verificationInfo; - installerPackageName = base.installerPackageName; - volumeUuid = base.volumeUuid; + verificationInfo = orig.verificationInfo; + versionCode = orig.versionCode; + volumeUuid = orig.volumeUuid; } private PackageUserState modifyUserState(int userId) { diff --git a/services/core/java/com/android/server/pm/PendingPackage.java b/services/core/java/com/android/server/pm/PendingPackage.java deleted file mode 100644 index da73085985ba..000000000000 --- a/services/core/java/com/android/server/pm/PendingPackage.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server.pm; - -import java.io.File; -import java.util.List; - -final class PendingPackage extends PackageSettingBase { - final int sharedId; - - PendingPackage(String name, String realName, File codePath, File resourcePath, - String legacyNativeLibraryPathString, String primaryCpuAbiString, - String secondaryCpuAbiString, String cpuAbiOverrideString, int sharedId, - int pVersionCode, int pkgFlags, int pkgPrivateFlags, String parentPackageName, - List<String> childPackageNames) { - super(name, realName, codePath, resourcePath, legacyNativeLibraryPathString, - primaryCpuAbiString, secondaryCpuAbiString, cpuAbiOverrideString, - pVersionCode, pkgFlags, pkgPrivateFlags, parentPackageName, childPackageNames); - this.sharedId = sharedId; - } -} diff --git a/services/core/java/com/android/server/pm/SELinuxMMAC.java b/services/core/java/com/android/server/pm/SELinuxMMAC.java index a6350fe8cf35..89705560db7d 100644 --- a/services/core/java/com/android/server/pm/SELinuxMMAC.java +++ b/services/core/java/com/android/server/pm/SELinuxMMAC.java @@ -19,6 +19,7 @@ package com.android.server.pm; import android.content.pm.PackageParser; import android.content.pm.Signature; import android.os.Environment; +import android.os.SystemProperties; import android.system.ErrnoException; import android.system.Os; import android.system.OsConstants; @@ -64,6 +65,8 @@ public final class SELinuxMMAC { // to synchronize access during policy load and access attempts. private static List<Policy> sPolicies = new ArrayList<>(); + private static final String PROP_FORCE_RESTORECON = "sys.force_restorecon"; + /** Path to version on rootfs */ private static final File VERSION_FILE = new File("/selinux_version"); @@ -322,6 +325,11 @@ public final class SELinuxMMAC { * @return Returns true if the restorecon should occur or false otherwise. */ public static boolean isRestoreconNeeded(File file) { + // To investigate boot timing, allow a property to always force restorecon + if (SystemProperties.getBoolean(PROP_FORCE_RESTORECON, false)) { + return true; + } + try { final byte[] buf = new byte[20]; final int len = Os.getxattr(file.getAbsolutePath(), XATTR_SEAPP_HASH, buf); diff --git a/services/core/java/com/android/server/pm/SettingBase.java b/services/core/java/com/android/server/pm/SettingBase.java index 2921032b5572..71e8d515444b 100644 --- a/services/core/java/com/android/server/pm/SettingBase.java +++ b/services/core/java/com/android/server/pm/SettingBase.java @@ -30,10 +30,19 @@ abstract class SettingBase { mPermissionsState = new PermissionsState(); } - SettingBase(SettingBase base) { - pkgFlags = base.pkgFlags; - pkgPrivateFlags = base.pkgPrivateFlags; - mPermissionsState = new PermissionsState(base.mPermissionsState); + SettingBase(SettingBase orig) { + mPermissionsState = new PermissionsState(); + doCopy(orig); + } + + public void copyFrom(SettingBase orig) { + doCopy(orig); + } + + private void doCopy(SettingBase orig) { + pkgFlags = orig.pkgFlags; + pkgPrivateFlags = orig.pkgPrivateFlags; + mPermissionsState.copyFrom(orig.mPermissionsState); } public PermissionsState getPermissionsState() { diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java index 31a1c36c7fd5..52313b1ce262 100644 --- a/services/core/java/com/android/server/pm/Settings.java +++ b/services/core/java/com/android/server/pm/Settings.java @@ -166,6 +166,7 @@ final class Settings { private static final boolean DEBUG_STOPPED = false; private static final boolean DEBUG_MU = false; private static final boolean DEBUG_KERNEL = false; + private static final boolean DEBUG_PARSER = false; private static final String RUNTIME_PERMISSIONS_FILE_NAME = "runtime-permissions.xml"; @@ -393,7 +394,7 @@ final class Settings { * TODO: make this just a local variable that is passed in during package * scanning to make it less confusing. */ - private final ArrayList<PendingPackage> mPendingPackages = new ArrayList<PendingPackage>(); + private final ArrayList<PackageSetting> mPendingPackages = new ArrayList<>(); private final File mSystemDir; @@ -427,18 +428,22 @@ final class Settings { mBackupStoppedPackagesFilename = new File(mSystemDir, "packages-stopped-backup.xml"); } - PackageSetting getPackageLPw(PackageParser.Package pkg, PackageSetting origPackage, + PackageSetting getPackageLPw(String pkgName) { + return peekPackageLPr(pkgName); + } + + PackageSetting getPackageWithBenefitsLPw(PackageParser.Package pkg, PackageSetting origPackage, String realName, SharedUserSetting sharedUser, File codePath, File resourcePath, String legacyNativeLibraryPathString, String primaryCpuAbi, String secondaryCpuAbi, - int pkgFlags, int pkgPrivateFlags, UserHandle user, boolean add) + int pkgFlags, int pkgPrivateFlags, UserHandle user) throws PackageManagerException { final String name = pkg.packageName; final String parentPackageName = (pkg.parentPackage != null) ? pkg.parentPackage.packageName : null; - PackageSetting p = getPackageLPw(name, origPackage, realName, sharedUser, codePath, - resourcePath, legacyNativeLibraryPathString, primaryCpuAbi, secondaryCpuAbi, - pkg.mVersionCode, pkgFlags, pkgPrivateFlags, user, add, true /*allowInstall*/, - parentPackageName, pkg.getChildPackageNames()); + PackageSetting p = getPackageWithBenefitsLPw(name, origPackage, realName, sharedUser, + codePath, resourcePath, legacyNativeLibraryPathString, primaryCpuAbi, + secondaryCpuAbi, pkg.mVersionCode, pkgFlags, pkgPrivateFlags, user, + true /*allowInstall*/, parentPackageName, pkg.getChildPackageNames()); return p; } @@ -602,7 +607,7 @@ final class Settings { p = new PackageSetting(name, realName, codePath, resourcePath, legacyNativeLibraryPathString, primaryCpuAbiString, secondaryCpuAbiString, cpuAbiOverrideString, vc, pkgFlags, pkgPrivateFlags, parentPackageName, - childPackageNames); + childPackageNames, 0 /*userId*/); p.appId = uid; if (addUserIdLPw(uid, p, name)) { mPackages.put(name, p); @@ -679,11 +684,11 @@ final class Settings { } } - private PackageSetting getPackageLPw(String name, PackageSetting origPackage, + private PackageSetting getPackageWithBenefitsLPw(String name, PackageSetting origPackage, String realName, SharedUserSetting sharedUser, File codePath, File resourcePath, String legacyNativeLibraryPathString, String primaryCpuAbiString, String secondaryCpuAbiString, int vc, int pkgFlags, int pkgPrivateFlags, - UserHandle installUser, boolean add, boolean allowInstall, String parentPackage, + UserHandle installUser, boolean allowInstall, String parentPackage, List<String> childPackageNames) throws PackageManagerException { final UserManagerService userManager = UserManagerService.getInstance(); final PackageSetting disabledPackage = getDisabledSystemPkgLPr(name); @@ -714,11 +719,6 @@ final class Settings { throw new PackageManagerException(INSTALL_FAILED_INSUFFICIENT_STORAGE, "Creating application package " + name + " failed"); } - if (add) { - // Finish adding new package by adding it and updating shared - // user preferences - addPackageSettingLPw(p, name, sharedUser); - } } if (peekPackageLPr(name) != null) { final List<UserInfo> allUsers = getAllUsers(UserManagerService.getInstance()); @@ -857,7 +857,7 @@ final class Settings { pkgSetting = new PackageSetting(originalPkg.name, pkgName, codePath, resourcePath, legacyNativeLibraryPath, primaryCpuAbi, secondaryCpuAbi, null /*cpuAbiOverrideString*/, versionCode, pkgFlags, pkgPrivateFlags, - parentPkgName, childPkgNames); + parentPkgName, childPkgNames, 0 /*sharedUserId*/); if (PackageManagerService.DEBUG_UPGRADE) Log.v(PackageManagerService.TAG, "Package " + pkgName + " is adopting original package " + originalPkg.name); // Note that we will retain the new package's signature so @@ -876,7 +876,7 @@ final class Settings { pkgSetting = new PackageSetting(pkgName, realPkgName, codePath, resourcePath, legacyNativeLibraryPath, primaryCpuAbi, secondaryCpuAbi, null /*cpuAbiOverrideString*/, versionCode, pkgFlags, pkgPrivateFlags, - parentPkgName, childPkgNames); + parentPkgName, childPkgNames, 0 /*sharedUserId*/); pkgSetting.setTimeStamp(codePath.lastModified()); pkgSetting.sharedUser = sharedUser; // If this is not a system app, it starts out stopped. @@ -1025,15 +1025,14 @@ final class Settings { if (p.sharedUser != null && p.sharedUser.signatures.mSignatures == null) { p.sharedUser.signatures.assignSignatures(pkg.mSignatures); } - addPackageSettingLPw(p, pkg.packageName, p.sharedUser); + addPackageSettingLPw(p, p.sharedUser); } // Utility method that adds a PackageSetting to mPackages and // completes updating the shared user attributes and any restored // app link verification state - private void addPackageSettingLPw(PackageSetting p, String name, - SharedUserSetting sharedUser) { - mPackages.put(name, p); + private void addPackageSettingLPw(PackageSetting p, SharedUserSetting sharedUser) { + mPackages.put(p.name, p); if (sharedUser != null) { if (p.sharedUser != null && p.sharedUser != sharedUser) { PackageManagerService.reportSettingsProblem(Log.ERROR, @@ -1067,12 +1066,12 @@ final class Settings { } } - IntentFilterVerificationInfo ivi = mRestoredIntentFilterVerifications.get(name); + IntentFilterVerificationInfo ivi = mRestoredIntentFilterVerifications.get(p.name); if (ivi != null) { if (DEBUG_DOMAIN_VERIFICATION) { - Slog.i(TAG, "Applying restored IVI for " + name + " : " + ivi.getStatusString()); + Slog.i(TAG, "Applying restored IVI for " + p.name + " : " + ivi.getStatusString()); } - mRestoredIntentFilterVerifications.remove(name); + mRestoredIntentFilterVerifications.remove(p.name); p.setIntentFilterVerificationInfo(ivi); } } @@ -1320,7 +1319,7 @@ final class Settings { /* package protected */ IntentFilterVerificationInfo createIntentFilterVerificationIfNeededLPw(String packageName, - ArrayList<String> domains) { + ArraySet<String> domains) { PackageSetting ps = mPackages.get(packageName); if (ps == null) { if (DEBUG_DOMAIN_VERIFICATION) { @@ -1595,7 +1594,9 @@ final class Settings { throws XmlPullParserException, IOException { IntentFilterVerificationInfo ivi = new IntentFilterVerificationInfo(parser); packageSetting.setIntentFilterVerificationInfo(ivi); - Log.d(TAG, "Read domain verification for package: " + ivi.getPackageName()); + if (DEBUG_PARSER) { + Log.d(TAG, "Read domain verification for package: " + ivi.getPackageName()); + } } private void readRestoredIntentFilterVerifications(XmlPullParser parser) @@ -3039,30 +3040,22 @@ final class Settings { final int N = mPendingPackages.size(); for (int i = 0; i < N; i++) { - final PendingPackage pp = mPendingPackages.get(i); - Object idObj = getUserIdLPr(pp.sharedId); - if (idObj != null && idObj instanceof SharedUserSetting) { - try { - PackageSetting p = getPackageLPw(pp.name, null, pp.realName, - (SharedUserSetting) idObj, pp.codePath, pp.resourcePath, - pp.legacyNativeLibraryPathString, pp.primaryCpuAbiString, - pp.secondaryCpuAbiString, pp.versionCode, pp.pkgFlags, - pp.pkgPrivateFlags, null /*installUser*/, true /*add*/, - false /*allowInstall*/, pp.parentPackageName, pp.childPackageNames); - p.copyFrom(pp); - } catch (PackageManagerException e) { - PackageManagerService.reportSettingsProblem(Log.WARN, - "Unable to create application package for " + pp.name); - continue; - } + final PackageSetting p = mPendingPackages.get(i); + final int sharedUserId = p.getSharedUserId(); + final Object idObj = getUserIdLPr(sharedUserId); + if (idObj instanceof SharedUserSetting) { + final SharedUserSetting sharedUser = (SharedUserSetting) idObj; + p.sharedUser = sharedUser; + p.appId = sharedUser.userId; + addPackageSettingLPw(p, sharedUser); } else if (idObj != null) { - String msg = "Bad package setting: package " + pp.name + " has shared uid " - + pp.sharedId + " that is not a shared uid\n"; + String msg = "Bad package setting: package " + p.name + " has shared uid " + + sharedUserId + " that is not a shared uid\n"; mReadMessages.append(msg); PackageManagerService.reportSettingsProblem(Log.ERROR, msg); } else { - String msg = "Bad package setting: package " + pp.name + " has shared uid " - + pp.sharedId + " that is not defined\n"; + String msg = "Bad package setting: package " + p.name + " has shared uid " + + sharedUserId + " that is not defined\n"; mReadMessages.append(msg); PackageManagerService.reportSettingsProblem(Log.ERROR, msg); } @@ -3535,7 +3528,7 @@ final class Settings { PackageSetting ps = new PackageSetting(name, realName, codePathFile, new File(resourcePathStr), legacyNativeLibraryPathStr, primaryCpuAbiStr, secondaryCpuAbiStr, cpuAbiOverrideStr, versionCode, pkgFlags, pkgPrivateFlags, - parentPackageName, null); + parentPackageName, null /*childPackageNames*/, 0 /*sharedUserId*/); String timeStampStr = parser.getAttributeValue(null, "ft"); if (timeStampStr != null) { try { @@ -3627,7 +3620,7 @@ final class Settings { long timeStamp = 0; long firstInstallTime = 0; long lastUpdateTime = 0; - PackageSettingBase packageSetting = null; + PackageSetting packageSetting = null; String version = null; int versionCode = 0; String parentPackageName; @@ -3746,7 +3739,8 @@ final class Settings { if (PackageManagerService.DEBUG_SETTINGS) Log.v(PackageManagerService.TAG, "Reading package: " + name + " userId=" + idStr + " sharedUserId=" + sharedIdStr); - int userId = idStr != null ? Integer.parseInt(idStr) : 0; + final int userId = idStr != null ? Integer.parseInt(idStr) : 0; + final int sharedUserId = sharedIdStr != null ? Integer.parseInt(sharedIdStr) : 0; if (resourcePathStr == null) { resourcePathStr = codePathStr; } @@ -3765,7 +3759,7 @@ final class Settings { packageSetting = addPackageLPw(name.intern(), realName, new File(codePathStr), new File(resourcePathStr), legacyNativeLibraryPathStr, primaryCpuAbiString, secondaryCpuAbiString, cpuAbiOverrideString, userId, versionCode, pkgFlags, - pkgPrivateFlags, parentPackageName, null); + pkgPrivateFlags, parentPackageName, null /*childPackageNames*/); if (PackageManagerService.DEBUG_SETTINGS) Log.i(PackageManagerService.TAG, "Reading package " + name + ": userId=" + userId + " pkg=" + packageSetting); @@ -3779,20 +3773,19 @@ final class Settings { packageSetting.lastUpdateTime = lastUpdateTime; } } else if (sharedIdStr != null) { - userId = sharedIdStr != null ? Integer.parseInt(sharedIdStr) : 0; - if (userId > 0) { - packageSetting = new PendingPackage(name.intern(), realName, new File( + if (sharedUserId > 0) { + packageSetting = new PackageSetting(name.intern(), realName, new File( codePathStr), new File(resourcePathStr), legacyNativeLibraryPathStr, primaryCpuAbiString, secondaryCpuAbiString, cpuAbiOverrideString, - userId, versionCode, pkgFlags, pkgPrivateFlags, parentPackageName, - null); + versionCode, pkgFlags, pkgPrivateFlags, parentPackageName, + null /*childPackageNames*/, sharedUserId); packageSetting.setTimeStamp(timeStamp); packageSetting.firstInstallTime = firstInstallTime; packageSetting.lastUpdateTime = lastUpdateTime; - mPendingPackages.add((PendingPackage) packageSetting); + mPendingPackages.add(packageSetting); if (PackageManagerService.DEBUG_SETTINGS) Log.i(PackageManagerService.TAG, "Reading package " + name - + ": sharedUserId=" + userId + " pkg=" + packageSetting); + + ": sharedUserId=" + sharedUserId + " pkg=" + packageSetting); } else { PackageManagerService.reportSettingsProblem(Log.WARN, "Error in package manager settings: package " + name diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java index d5767b4cad8a..c1fc7f114c67 100644 --- a/services/core/java/com/android/server/pm/ShortcutService.java +++ b/services/core/java/com/android/server/pm/ShortcutService.java @@ -878,6 +878,9 @@ public class ShortcutService extends IShortcutService.Stub { saveUserInternalLocked(userId, os, /* forBackup= */ false); file.finishWrite(os); + + // Remove all dangling bitmap files. + cleanupDanglingBitmapDirectoriesLocked(userId); } catch (XmlPullParserException | IOException e) { Slog.e(TAG, "Failed to write to file " + file.getBaseFile(), e); file.failWrite(os); @@ -929,7 +932,6 @@ public class ShortcutService extends IShortcutService.Stub { } try { final ShortcutUser ret = loadUserInternal(userId, in, /* forBackup= */ false); - cleanupDanglingBitmapDirectoriesLocked(userId, ret); return ret; } catch (IOException | XmlPullParserException e) { Slog.e(TAG, "Failed to read file " + file.getBaseFile(), e); @@ -1062,9 +1064,22 @@ public class ShortcutService extends IShortcutService.Stub { } } - // Requires mLock held, but "Locked" prefix would look weired so we jsut say "L". + // Requires mLock held, but "Locked" prefix would look weired so we just say "L". protected boolean isUserUnlockedL(@UserIdInt int userId) { - return mUnlockedUsers.get(userId); + // First, check the local copy. + if (mUnlockedUsers.get(userId)) { + return true; + } + // If the local copy says the user is locked, check with AM for the actual state, since + // the user might just have been unlocked. + // Note we just don't use isUserUnlockingOrUnlocked() here, because it'll return false + // when the user is STOPPING, which we still want to consider as "unlocked". + final long token = injectClearCallingIdentity(); + try { + return mUserManager.isUserUnlockingOrUnlocked(userId); + } finally { + injectRestoreCallingIdentity(token); + } } // Requires mLock held, but "Locked" prefix would look weired so we jsut say "L". @@ -1125,14 +1140,8 @@ public class ShortcutService extends IShortcutService.Stub { // === Caller validation === void removeIcon(@UserIdInt int userId, ShortcutInfo shortcut) { - if (shortcut.getBitmapPath() != null) { - if (DEBUG) { - Slog.d(TAG, "Removing " + shortcut.getBitmapPath()); - } - new File(shortcut.getBitmapPath()).delete(); - - shortcut.setBitmapPath(null); - } + // Do not remove the actual bitmap file yet, because if the device crashes before saving + // he XML we'd lose the icon. We just remove all dangling files after saving the XML. shortcut.setIconResourceId(0); shortcut.setIconResName(null); shortcut.clearFlags(ShortcutInfo.FLAG_HAS_ICON_FILE | ShortcutInfo.FLAG_HAS_ICON_RES); @@ -1148,13 +1157,14 @@ public class ShortcutService extends IShortcutService.Stub { } } - private void cleanupDanglingBitmapDirectoriesLocked( - @UserIdInt int userId, @NonNull ShortcutUser user) { + private void cleanupDanglingBitmapDirectoriesLocked(@UserIdInt int userId) { if (DEBUG) { Slog.d(TAG, "cleanupDanglingBitmaps: userId=" + userId); } final long start = injectElapsedRealtime(); + final ShortcutUser user = getUserShortcutsLocked(userId); + final File bitmapDir = getUserBitmapFilePath(userId); final File[] children = bitmapDir.listFiles(); if (children == null) { diff --git a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java index 772c64ea2171..3df13a9c637f 100644 --- a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java +++ b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java @@ -26,11 +26,9 @@ import android.app.ActivityManager; import android.app.ActivityManagerNative; import android.content.ContentResolver; import android.content.Context; -import android.net.Uri; import android.os.Binder; import android.os.Bundle; import android.os.RemoteException; -import android.os.SystemProperties; import android.os.UserHandle; import android.os.UserManager; import android.service.persistentdata.PersistentDataBlockManager; @@ -188,8 +186,7 @@ public class UserRestrictionsUtils { serializer.endTag(null, tag); } - public static void readRestrictions(XmlPullParser parser, Bundle restrictions) - throws IOException { + public static void readRestrictions(XmlPullParser parser, Bundle restrictions) { for (String key : USER_RESTRICTIONS) { final String value = parser.getAttributeValue(null, key); if (value != null) { @@ -437,7 +434,13 @@ public class UserRestrictionsUtils { if (newValue) { PersistentDataBlockManager manager = (PersistentDataBlockManager) context .getSystemService(Context.PERSISTENT_DATA_BLOCK_SERVICE); - if (manager != null && manager.getOemUnlockEnabled()) { + if (manager != null + && manager.getOemUnlockEnabled() + && manager.getFlashLockState() + != PersistentDataBlockManager.FLASH_LOCK_UNLOCKED) { + // Only disable OEM unlock if the bootloader is locked. If it's already + // unlocked, setting the OEM unlock enabled flag to false has no effect + // (the bootloader would remain unlocked). manager.setOemUnlockEnabled(false); } } diff --git a/services/core/java/com/android/server/policy/GlobalActions.java b/services/core/java/com/android/server/policy/GlobalActions.java index 6fc15f0216e4..bb91f76ecf30 100644 --- a/services/core/java/com/android/server/policy/GlobalActions.java +++ b/services/core/java/com/android/server/policy/GlobalActions.java @@ -103,6 +103,7 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac private static final String GLOBAL_ACTION_KEY_LOCKDOWN = "lockdown"; private static final String GLOBAL_ACTION_KEY_VOICEASSIST = "voiceassist"; private static final String GLOBAL_ACTION_KEY_ASSIST = "assist"; + private static final String GLOBAL_ACTION_KEY_RESTART = "restart"; private final Context mContext; private final WindowManagerFuncs mWindowManagerFuncs; @@ -298,6 +299,8 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac mItems.add(getVoiceAssistAction()); } else if (GLOBAL_ACTION_KEY_ASSIST.equals(actionKey)) { mItems.add(getAssistAction()); + } else if (GLOBAL_ACTION_KEY_RESTART.equals(actionKey)) { + mItems.add(new RestartAction()); } else { Log.e(TAG, "Invalid global action key " + actionKey); } @@ -369,6 +372,38 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac } } + private final class RestartAction extends SinglePressAction implements LongPressAction { + private RestartAction() { + super(R.drawable.ic_restart, R.string.global_action_restart); + } + + @Override + public boolean onLongPress() { + UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE); + if (!um.hasUserRestriction(UserManager.DISALLOW_SAFE_BOOT)) { + mWindowManagerFuncs.rebootSafeMode(true); + return true; + } + return false; + } + + @Override + public boolean showDuringKeyguard() { + return true; + } + + @Override + public boolean showBeforeProvisioning() { + return true; + } + + @Override + public void onPress() { + mWindowManagerFuncs.reboot(false /* confirm */); + } + } + + private class BugReportAction extends SinglePressAction implements LongPressAction { public BugReportAction() { diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java index 60fbabfa18f0..9ce147d29d63 100644 --- a/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -7392,8 +7392,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { } private boolean areSystemNavigationKeysEnabled() { - return Settings.Secure.getInt(mContext.getContentResolver(), - Settings.Secure.SYSTEM_NAVIGATION_KEYS_ENABLED, 0) == 1; + return Settings.Secure.getIntForUser(mContext.getContentResolver(), + Settings.Secure.SYSTEM_NAVIGATION_KEYS_ENABLED, 0, UserHandle.USER_CURRENT) == 1; } @Override diff --git a/services/core/java/com/android/server/trust/TrustArchive.java b/services/core/java/com/android/server/trust/TrustArchive.java index fd63d486d049..aaac2979049b 100644 --- a/services/core/java/com/android/server/trust/TrustArchive.java +++ b/services/core/java/com/android/server/trust/TrustArchive.java @@ -37,6 +37,7 @@ public class TrustArchive { private static final int TYPE_AGENT_CONNECTED = 4; private static final int TYPE_AGENT_STOPPED = 5; private static final int TYPE_MANAGING_TRUST = 6; + private static final int TYPE_POLICY_CHANGED = 7; private static final int HISTORY_LIMIT = 200; @@ -99,6 +100,10 @@ public class TrustArchive { addEvent(new Event(TYPE_MANAGING_TRUST, userId, agent, null, 0, 0, managing)); } + public void logDevicePolicyChanged() { + addEvent(new Event(TYPE_POLICY_CHANGED, UserHandle.USER_ALL, null, null, 0, 0, false)); + } + private void addEvent(Event e) { if (mEvents.size() >= HISTORY_LIMIT) { mEvents.removeFirst(); @@ -112,7 +117,8 @@ public class TrustArchive { Iterator<Event> iter = mEvents.descendingIterator(); while (iter.hasNext() && count < limit) { Event ev = iter.next(); - if (userId != UserHandle.USER_ALL && userId != ev.userId) { + if (userId != UserHandle.USER_ALL && userId != ev.userId + && ev.userId != UserHandle.USER_ALL) { continue; } @@ -122,11 +128,13 @@ public class TrustArchive { if (userId == UserHandle.USER_ALL) { writer.print("user="); writer.print(ev.userId); writer.print(", "); } - writer.print("agent="); - if (duplicateSimpleNames) { - writer.print(ev.agent.flattenToShortString()); - } else { - writer.print(getSimpleName(ev.agent)); + if (ev.agent != null) { + writer.print("agent="); + if (duplicateSimpleNames) { + writer.print(ev.agent.flattenToShortString()); + } else { + writer.print(getSimpleName(ev.agent)); + } } switch (ev.type) { case TYPE_GRANT_TRUST: @@ -181,6 +189,8 @@ public class TrustArchive { return "AgentStopped"; case TYPE_MANAGING_TRUST: return "ManagingTrust"; + case TYPE_POLICY_CHANGED: + return "DevicePolicyChanged"; default: return "Unknown(" + type + ")"; } diff --git a/services/core/java/com/android/server/trust/TrustManagerService.java b/services/core/java/com/android/server/trust/TrustManagerService.java index e60488a48bdd..216afe610261 100644 --- a/services/core/java/com/android/server/trust/TrustManagerService.java +++ b/services/core/java/com/android/server/trust/TrustManagerService.java @@ -434,12 +434,17 @@ public class TrustManagerService extends SystemService { } void updateDevicePolicyFeatures() { + boolean changed = false; for (int i = 0; i < mActiveAgents.size(); i++) { AgentInfo info = mActiveAgents.valueAt(i); if (info.agent.isConnected()) { info.agent.updateDevicePolicyFeatures(); + changed = true; } } + if (changed) { + mArchive.logDevicePolicyChanged(); + } } private void removeAgentsOfPackage(String packageName) { diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java index 95fbf554bf66..76f2f0e43e9b 100644 --- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java +++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java @@ -1400,9 +1400,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub { wallpaper.whichPending = which; wallpaper.setComplete = completion; wallpaper.cropHint.set(cropHint); - if ((which & FLAG_SYSTEM) != 0) { - wallpaper.allowBackup = allowBackup; - } + wallpaper.allowBackup = allowBackup; } return pfd; } finally { @@ -1753,12 +1751,14 @@ public class WallpaperManagerService extends IWallpaperManager.Stub { } @Override - public boolean isWallpaperBackupEligible(int userId) { + public boolean isWallpaperBackupEligible(int which, int userId) { if (Binder.getCallingUid() != Process.SYSTEM_UID) { throw new SecurityException("Only the system may call isWallpaperBackupEligible"); } - WallpaperData wallpaper = getWallpaperSafeLocked(userId, FLAG_SYSTEM); + WallpaperData wallpaper = (which == FLAG_LOCK) + ? mWallpaperMap.get(userId) + : mLockWallpaperMap.get(userId); return (wallpaper != null) ? wallpaper.allowBackup : false; } diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java index c78e94bff793..d3dab440c44a 100644 --- a/services/core/java/com/android/server/wm/AppWindowToken.java +++ b/services/core/java/com/android/server/wm/AppWindowToken.java @@ -517,6 +517,11 @@ class AppWindowToken extends WindowToken { // placement for this window during this period, one or more frame will // show up with wrong position or scale. win.mWinAnimator.mAnimating = false; + + if (win.mDestroying) { + win.mDestroying = false; + mService.mDestroySurface.remove(win); + } } } requestUpdateWallpaperIfNeeded(); diff --git a/services/core/java/com/android/server/wm/DragState.java b/services/core/java/com/android/server/wm/DragState.java index 9d0fb618515a..d0167bb6f00b 100644 --- a/services/core/java/com/android/server/wm/DragState.java +++ b/services/core/java/com/android/server/wm/DragState.java @@ -94,10 +94,7 @@ class DragState { float mOriginalX, mOriginalY; float mCurrentX, mCurrentY; float mThumbOffsetX, mThumbOffsetY; - InputChannel mServerChannel, mClientChannel; - DragInputEventReceiver mInputEventReceiver; - InputApplicationHandle mDragApplicationHandle; - InputWindowHandle mDragWindowHandle; + InputInterceptor mInputInterceptor; WindowState mTargetWindow; ArrayList<WindowState> mNotifiedWindows; boolean mDragInProgress; @@ -130,16 +127,13 @@ class DragState { mNotifiedWindows = null; } - /** - * @param display The Display that the window being dragged is on. - */ - void register(Display display) { - if (DEBUG_DRAG) Slog.d(TAG_WM, "registering drag input channel"); - if (mClientChannel != null) { - Slog.e(TAG_WM, "Duplicate register of drag input channel"); - } else { - mDisplayContent = mService.getDisplayContentLocked(display.getDisplayId()); + class InputInterceptor { + InputChannel mServerChannel, mClientChannel; + DragInputEventReceiver mInputEventReceiver; + InputApplicationHandle mDragApplicationHandle; + InputWindowHandle mDragWindowHandle; + InputInterceptor(Display display) { InputChannel[] channels = InputChannel.openInputChannelPair("drag"); mServerChannel = channels[0]; mClientChannel = channels[1]; @@ -188,13 +182,8 @@ class DragState { } mService.pauseRotationLocked(); } - } - void unregister() { - if (DEBUG_DRAG) Slog.d(TAG_WM, "unregistering drag input channel"); - if (mClientChannel == null) { - Slog.e(TAG_WM, "Unregister of nonexistent drag input channel"); - } else { + void tearDown() { mService.mInputManager.unregisterInputChannel(mServerChannel); mInputEventReceiver.dispose(); mInputEventReceiver = null; @@ -214,6 +203,40 @@ class DragState { } } + InputChannel getInputChannel() { + return mInputInterceptor == null ? null : mInputInterceptor.mServerChannel; + } + + InputWindowHandle getInputWindowHandle() { + return mInputInterceptor == null ? null : mInputInterceptor.mDragWindowHandle; + } + + /** + * @param display The Display that the window being dragged is on. + */ + void register(Display display) { + if (DEBUG_DRAG) Slog.d(TAG_WM, "registering drag input channel"); + if (mInputInterceptor != null) { + Slog.e(TAG_WM, "Duplicate register of drag input channel"); + } else { + mInputInterceptor = new InputInterceptor(display); + mService.mInputMonitor.updateInputWindowsLw(true /*force*/); + } + } + + void unregister() { + if (DEBUG_DRAG) Slog.d(TAG_WM, "unregistering drag input channel"); + if (mInputInterceptor == null) { + Slog.e(TAG_WM, "Unregister of nonexistent drag input channel"); + } else { + // Input channel should be disposed on the thread where the input is being handled. + mService.mH.obtainMessage( + H.TEAR_DOWN_DRAG_AND_DROP_INPUT, mInputInterceptor).sendToTarget(); + mInputInterceptor = null; + mService.mInputMonitor.updateInputWindowsLw(true /*force*/); + } + } + int getDragLayerLw() { return mService.mPolicy.windowTypeToLayerLw(WindowManager.LayoutParams.TYPE_DRAG) * WindowManagerService.TYPE_LAYER_MULTIPLIER @@ -397,8 +420,6 @@ class DragState { // free our resources and drop all the object references reset(); mService.mDragState = null; - - mService.mInputMonitor.updateInputWindowsLw(true /*force*/); } void notifyMoveLw(float x, float y) { diff --git a/services/core/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java index b9c55a576251..535ce9dba2eb 100644 --- a/services/core/java/com/android/server/wm/InputMonitor.java +++ b/services/core/java/com/android/server/wm/InputMonitor.java @@ -249,7 +249,7 @@ final class InputMonitor implements InputManagerService.WindowManagerCallbacks { if (DEBUG_DRAG) { Log.d(TAG_WM, "Inserting drag window"); } - final InputWindowHandle dragWindowHandle = mService.mDragState.mDragWindowHandle; + final InputWindowHandle dragWindowHandle = mService.mDragState.getInputWindowHandle(); if (dragWindowHandle != null) { addInputWindowHandleLw(dragWindowHandle); } else { diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java index 08c0a4b01357..cb99461ec334 100644 --- a/services/core/java/com/android/server/wm/Session.java +++ b/services/core/java/com/android/server/wm/Session.java @@ -324,16 +324,16 @@ final class Session extends IWindowSession.Stub } Display display = displayContent.getDisplay(); mService.mDragState.register(display); - mService.mInputMonitor.updateInputWindowsLw(true /*force*/); if (!mService.mInputManager.transferTouchFocus(callingWin.mInputChannel, - mService.mDragState.mServerChannel)) { + mService.mDragState.getInputChannel())) { Slog.e(TAG_WM, "Unable to transfer touch focus"); mService.mDragState.unregister(); + mService.mDragState.reset(); mService.mDragState = null; - mService.mInputMonitor.updateInputWindowsLw(true /*force*/); return false; } + mService.mDragState.mDisplayContent = displayContent; mService.mDragState.mData = data; mService.mDragState.broadcastDragStartedLw(touchX, touchY); mService.mDragState.overridePointerIconLw(touchSource); diff --git a/services/core/java/com/android/server/wm/WindowAnimator.java b/services/core/java/com/android/server/wm/WindowAnimator.java index 6515fbdd0587..34fa1b023dce 100644 --- a/services/core/java/com/android/server/wm/WindowAnimator.java +++ b/services/core/java/com/android/server/wm/WindowAnimator.java @@ -119,6 +119,8 @@ public class WindowAnimator { // check if some got replaced and can be removed. private boolean mRemoveReplacedWindows = false; + private final AppTokenList mTmpExitingAppTokens = new AppTokenList(); + private String forceHidingToString() { switch (mForceHiding) { case KEYGUARD_NOT_SHOWN: return "KEYGUARD_NOT_SHOWN"; @@ -189,10 +191,19 @@ public class WindowAnimator { } } - final AppTokenList exitingAppTokens = stack.mExitingAppTokens; - final int exitingCount = exitingAppTokens.size(); + mTmpExitingAppTokens.clear(); + mTmpExitingAppTokens.addAll(stack.mExitingAppTokens); + + final int exitingCount = mTmpExitingAppTokens.size(); for (int i = 0; i < exitingCount; i++) { - final AppWindowAnimator appAnimator = exitingAppTokens.get(i).mAppAnimator; + final AppWindowAnimator appAnimator = mTmpExitingAppTokens.get(i).mAppAnimator; + // stepAnimation can trigger finishExit->removeWindowInnerLocked + // ->performSurfacePlacement + // performSurfacePlacement will directly manipulate the mExitingAppTokens list + // so we need to iterate over a copy and check for modifications. + if (!stack.mExitingAppTokens.contains(appAnimator)) { + continue; + } appAnimator.wasAnimating = appAnimator.animating; if (appAnimator.stepAnimationLocked(mCurrentTime, displayId)) { setAnimating(true); diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 8f7896e28013..22120d016af4 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -771,9 +771,16 @@ public class WindowManagerService extends IWindowManager.Stub public void onInputEvent(InputEvent event) { boolean handled = false; try { + if (mDragState == null) { + // The drag has ended but the clean-up message has not been processed by + // window manager. Drop events that occur after this until window manager + // has a chance to clean-up the input handle. + handled = true; + return; + } if (event instanceof MotionEvent && (event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0 - && mDragState != null && !mMuteInput) { + && !mMuteInput) { final MotionEvent motionEvent = (MotionEvent)event; boolean endDrag = false; final float newX = motionEvent.getRawX(); @@ -833,6 +840,8 @@ public class WindowManagerService extends IWindowManager.Stub if (DEBUG_DRAG) Slog.d(TAG_WM, "Drag ended; tearing down state"); // tell all the windows that the drag has ended synchronized (mWindowMap) { + // endDragLw will post back to looper to dispose the receiver + // since we still need the receiver for the last finishInputEvent. mDragState.endDragLw(); } mStylusButtonDownAtStart = false; @@ -4718,6 +4727,12 @@ public class WindowManagerService extends IWindowManager.Stub // Called by window manager policy. Not exposed externally. @Override + public void reboot(boolean confirm) { + ShutdownThread.reboot(mContext, PowerManager.SHUTDOWN_USER_REQUESTED, confirm); + } + + // Called by window manager policy. Not exposed externally. + @Override public void rebootSafeMode(boolean confirm) { ShutdownThread.rebootSafeMode(mContext, confirm); } @@ -7099,6 +7114,7 @@ public class WindowManagerService extends IWindowManager.Stub public static final int RESIZE_STACK = 42; public static final int RESIZE_TASK = 43; + public static final int TEAR_DOWN_DRAG_AND_DROP_INPUT = 44; public static final int WINDOW_REPLACEMENT_TIMEOUT = 46; @@ -7511,7 +7527,6 @@ public class WindowManagerService extends IWindowManager.Stub // !!! TODO: ANR the app that has failed to start the drag in time if (mDragState != null) { mDragState.unregister(); - mInputMonitor.updateInputWindowsLw(true /*force*/); mDragState.reset(); mDragState = null; } @@ -7534,6 +7549,17 @@ public class WindowManagerService extends IWindowManager.Stub break; } + case TEAR_DOWN_DRAG_AND_DROP_INPUT: { + if (DEBUG_DRAG) Slog.d(TAG_WM, "Drag ending; tearing down input channel"); + DragState.InputInterceptor interceptor = (DragState.InputInterceptor) msg.obj; + if (interceptor != null) { + synchronized (mWindowMap) { + interceptor.tearDown(); + } + } + } + break; + case REPORT_HARD_KEYBOARD_STATUS_CHANGE: { notifyHardKeyboardStatusChange(); break; diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java index 0fcf0c71e474..dfee8de144d2 100644 --- a/services/core/java/com/android/server/wm/WindowStateAnimator.java +++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java @@ -845,6 +845,22 @@ class WindowStateAnimator { mPendingDestroySurface = null; } + void applyMagnificationSpec(MagnificationSpec spec, Matrix transform) { + final int surfaceInsetLeft = mWin.mAttrs.surfaceInsets.left; + final int surfaceInsetTop = mWin.mAttrs.surfaceInsets.top; + + if (spec != null && !spec.isNop()) { + float scale = spec.scale; + transform.postScale(scale, scale); + transform.postTranslate(spec.offsetX, spec.offsetY); + + // As we are scaling the whole surface, to keep the content + // in the same position we will also have to scale the surfaceInsets. + transform.postTranslate(-(surfaceInsetLeft*scale - surfaceInsetLeft), + -(surfaceInsetTop*scale - surfaceInsetTop)); + } + } + void computeShownFrameLocked() { final boolean selfTransformation = mHasLocalTransformation; Transformation attachedTransformation = @@ -935,10 +951,7 @@ class WindowStateAnimator { if (mService.mAccessibilityController != null && displayId == DEFAULT_DISPLAY) { MagnificationSpec spec = mService.mAccessibilityController .getMagnificationSpecForWindowLocked(mWin); - if (spec != null && !spec.isNop()) { - tmpMatrix.postScale(spec.scale, spec.scale); - tmpMatrix.postTranslate(spec.offsetX, spec.offsetY); - } + applyMagnificationSpec(spec, tmpMatrix); } // "convert" it into SurfaceFlinger's format @@ -1037,10 +1050,7 @@ class WindowStateAnimator { tmpMatrix.setScale(mWin.mGlobalScale, mWin.mGlobalScale); tmpMatrix.postTranslate(frame.left + mWin.mXOffset, frame.top + mWin.mYOffset); - if (spec != null && !spec.isNop()) { - tmpMatrix.postScale(spec.scale, spec.scale); - tmpMatrix.postTranslate(spec.offsetX, spec.offsetY); - } + applyMagnificationSpec(spec, tmpMatrix); tmpMatrix.getValues(tmpFloats); @@ -1896,11 +1906,13 @@ class WindowStateAnimator { if (mDeferTransactionUntilFrame < 0) { return; } + final WindowState parentWindow = mWin.getParentWindow(); long time = System.currentTimeMillis(); if (time > mDeferTransactionTime + PENDING_TRANSACTION_FINISH_WAIT_TIME) { mDeferTransactionTime = -1; mDeferTransactionUntilFrame = -1; - } else { + } else if (parentWindow != null && + parentWindow.mWinAnimator.hasSurface()) { mSurfaceController.deferTransactionUntil( mWin.getParentWindow().mWinAnimator.mSurfaceController.getHandle(), mDeferTransactionUntilFrame); diff --git a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java index c26c07804e53..4c9211a635da 100644 --- a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java +++ b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java @@ -1462,7 +1462,7 @@ class WindowSurfacePlacer { mObscured = true; } - if (w.mHasSurface) { + if (w.mHasSurface && canBeSeen) { if ((attrFlags&FLAG_KEEP_SCREEN_ON) != 0) { mHoldScreen = w.mSession; mHoldScreenWindow = w; @@ -1485,43 +1485,39 @@ class WindowSurfacePlacer { } final int type = attrs.type; - if (canBeSeen - && (type == TYPE_SYSTEM_DIALOG - || type == TYPE_SYSTEM_ERROR - || (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0)) { + if (type == TYPE_SYSTEM_DIALOG || type == TYPE_SYSTEM_ERROR + || (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) { mSyswin = true; } - if (canBeSeen) { - // This function assumes that the contents of the default display are - // processed first before secondary displays. - final DisplayContent displayContent = w.getDisplayContent(); - if (displayContent != null && displayContent.isDefaultDisplay) { - // While a dream or keyguard is showing, obscure ordinary application - // content on secondary displays (by forcibly enabling mirroring unless - // there is other content we want to show) but still allow opaque - // keyguard dialogs to be shown. - if (type == TYPE_DREAM || (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) { - mObscureApplicationContentOnSecondaryDisplays = true; - } - mDisplayHasContent = true; - } else if (displayContent != null && - (!mObscureApplicationContentOnSecondaryDisplays - || (mObscured && type == TYPE_KEYGUARD_DIALOG))) { - // Allow full screen keyguard presentation dialogs to be seen. - mDisplayHasContent = true; - } - if (mPreferredRefreshRate == 0 - && w.mAttrs.preferredRefreshRate != 0) { - mPreferredRefreshRate = w.mAttrs.preferredRefreshRate; - } - if (mPreferredModeId == 0 - && w.mAttrs.preferredDisplayModeId != 0) { - mPreferredModeId = w.mAttrs.preferredDisplayModeId; - } - if ((privateflags & PRIVATE_FLAG_SUSTAINED_PERFORMANCE_MODE) != 0) { - mSustainedPerformanceModeCurrent = true; + // This function assumes that the contents of the default display are + // processed first before secondary displays. + final DisplayContent displayContent = w.getDisplayContent(); + if (displayContent != null && displayContent.isDefaultDisplay) { + // While a dream or keyguard is showing, obscure ordinary application + // content on secondary displays (by forcibly enabling mirroring unless + // there is other content we want to show) but still allow opaque + // keyguard dialogs to be shown. + if (type == TYPE_DREAM || (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) { + mObscureApplicationContentOnSecondaryDisplays = true; } + mDisplayHasContent = true; + } else if (displayContent != null && + (!mObscureApplicationContentOnSecondaryDisplays + || (mObscured && type == TYPE_KEYGUARD_DIALOG))) { + // Allow full screen keyguard presentation dialogs to be seen. + mDisplayHasContent = true; + } + if (mPreferredRefreshRate == 0 + && w.mAttrs.preferredRefreshRate != 0) { + mPreferredRefreshRate = w.mAttrs.preferredRefreshRate; + } + if (mPreferredModeId == 0 + && w.mAttrs.preferredDisplayModeId != 0) { + mPreferredModeId = w.mAttrs.preferredDisplayModeId; + } + if ((privateflags & PRIVATE_FLAG_SUSTAINED_PERFORMANCE_MODE) != 0) { + mSustainedPerformanceModeCurrent = true; } } } diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index f0cf3201cfe5..548f8314e97c 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -810,10 +810,8 @@ public final class SystemServer { traceBeginAndSlog("StartNetworkPolicyManagerService"); try { - networkPolicy = new NetworkPolicyManagerService( - context, mActivityManagerService, - (IPowerManager)ServiceManager.getService(Context.POWER_SERVICE), - networkStats, networkManagement); + networkPolicy = new NetworkPolicyManagerService(context, + mActivityManagerService, networkStats, networkManagement); ServiceManager.addService(Context.NETWORK_POLICY_SERVICE, networkPolicy); } catch (Throwable e) { reportWtf("starting NetworkPolicy Service", e); @@ -1013,6 +1011,10 @@ public final class SystemServer { mSystemServiceManager.startService(SoundTriggerService.class); if (!disableNonCoreServices) { + if (!disableTrustManager) { + mSystemServiceManager.startService(TrustManagerService.class); + } + if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_BACKUP)) { mSystemServiceManager.startService(BACKUP_MANAGER_SERVICE_CLASS); } @@ -1142,10 +1144,6 @@ public final class SystemServer { } Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER); - if (!disableTrustManager) { - mSystemServiceManager.startService(TrustManagerService.class); - } - if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)) { mSystemServiceManager.startService(FingerprintService.class); } diff --git a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java index 979f160d3c7b..6247089953ad 100644 --- a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java @@ -16,17 +16,12 @@ package com.android.server; -import static android.content.Intent.ACTION_UID_REMOVED; -import static android.content.Intent.EXTRA_UID; import static android.net.ConnectivityManager.CONNECTIVITY_ACTION; import static android.net.ConnectivityManager.TYPE_WIFI; -import static android.net.NetworkPolicy.CYCLE_NONE; import static android.net.NetworkPolicy.LIMIT_DISABLED; import static android.net.NetworkPolicy.WARNING_DISABLED; import static android.net.NetworkPolicyManager.POLICY_NONE; import static android.net.NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND; -import static android.net.NetworkPolicyManager.RULE_ALLOW_ALL; -import static android.net.NetworkPolicyManager.RULE_REJECT_METERED; import static android.net.NetworkPolicyManager.computeLastCycleBoundary; import static android.net.NetworkPolicyManager.computeNextCycleBoundary; import static android.net.TrafficStats.KB_IN_BYTES; @@ -34,28 +29,42 @@ import static android.net.TrafficStats.MB_IN_BYTES; import static android.text.format.DateUtils.DAY_IN_MILLIS; import static android.text.format.DateUtils.MINUTE_IN_MILLIS; import static android.text.format.Time.TIMEZONE_UTC; + import static com.android.server.net.NetworkPolicyManagerService.TYPE_LIMIT; import static com.android.server.net.NetworkPolicyManagerService.TYPE_LIMIT_SNOOZED; import static com.android.server.net.NetworkPolicyManagerService.TYPE_WARNING; -import static org.easymock.EasyMock.anyInt; -import static org.easymock.EasyMock.anyLong; -import static org.easymock.EasyMock.aryEq; -import static org.easymock.EasyMock.capture; -import static org.easymock.EasyMock.createMock; -import static org.easymock.EasyMock.eq; -import static org.easymock.EasyMock.expect; -import static org.easymock.EasyMock.expectLastCall; -import static org.easymock.EasyMock.isA; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyBoolean; +import static org.mockito.Matchers.anyInt; +import static org.mockito.Matchers.anyLong; +import static org.mockito.Matchers.anyString; +import static org.mockito.Matchers.eq; +import static org.mockito.Matchers.isA; +import static org.mockito.Mockito.atLeastOnce; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import android.app.ActivityManager; import android.app.IActivityManager; import android.app.INotificationManager; -import android.app.IProcessObserver; +import android.app.IUidObserver; import android.app.Notification; +import android.app.usage.UsageStatsManagerInternal; +import android.content.Context; import android.content.Intent; +import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.Signature; -import android.net.ConnectivityManager; import android.net.IConnectivityManager; import android.net.INetworkManagementEventObserver; import android.net.INetworkPolicyListener; @@ -69,40 +78,47 @@ import android.net.NetworkStats; import android.net.NetworkTemplate; import android.os.Binder; import android.os.INetworkManagementService; -import android.os.IPowerManager; -import android.os.MessageQueue.IdleHandler; +import android.os.PowerManagerInternal; import android.os.UserHandle; -import android.test.AndroidTestCase; -import android.test.mock.MockPackageManager; -import android.test.suitebuilder.annotation.LargeTest; -import android.test.suitebuilder.annotation.Suppress; +import android.support.test.InstrumentationRegistry; +import android.support.test.runner.AndroidJUnit4; import android.text.format.Time; +import android.util.Log; import android.util.TrustedTime; +import com.android.server.net.NetworkPolicyManagerInternal; import com.android.server.net.NetworkPolicyManagerService; + +import libcore.io.IoUtils; + import com.google.common.util.concurrent.AbstractFuture; -import org.easymock.Capture; -import org.easymock.EasyMock; -import org.easymock.IAnswer; +import org.junit.After; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; import java.io.File; -import java.util.Calendar; +import java.util.ArrayList; import java.util.LinkedHashSet; -import java.util.TimeZone; +import java.util.List; +import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; -import java.util.logging.Handler; - -import libcore.io.IoUtils; /** * Tests for {@link NetworkPolicyManagerService}. */ -@LargeTest -public class NetworkPolicyManagerServiceTest extends AndroidTestCase { +@RunWith(AndroidJUnit4.class) +public class NetworkPolicyManagerServiceTest { private static final String TAG = "NetworkPolicyManagerServiceTest"; private static final long TEST_START = 1194220800000L; @@ -114,20 +130,19 @@ public class NetworkPolicyManagerServiceTest extends AndroidTestCase { private BroadcastInterceptingContext mServiceContext; private File mPolicyDir; - private IActivityManager mActivityManager; - private IPowerManager mPowerManager; - private INetworkStatsService mStatsService; - private INetworkManagementService mNetworkManager; - private INetworkPolicyListener mPolicyListener; - private TrustedTime mTime; - private IConnectivityManager mConnManager; - private INotificationManager mNotifManager; + private @Mock IActivityManager mActivityManager; + private @Mock INetworkStatsService mStatsService; + private @Mock INetworkManagementService mNetworkManager; + private @Mock TrustedTime mTime; + private @Mock IConnectivityManager mConnManager; + private @Mock INotificationManager mNotifManager; + private @Mock PackageManager mPackageManager; - private NetworkPolicyManagerService mService; - private IProcessObserver mProcessObserver; + private IUidObserver mUidObserver; private INetworkManagementEventObserver mNetworkObserver; - private Binder mStubBinder = new Binder(); + private NetworkPolicyListenerAnswer mPolicyListener; + private NetworkPolicyManagerService mService; private long mStartTime; private long mElapsedRealtime; @@ -140,39 +155,30 @@ public class NetworkPolicyManagerServiceTest extends AndroidTestCase { private static final int UID_A = UserHandle.getUid(USER_ID, APP_ID_A); private static final int UID_B = UserHandle.getUid(USER_ID, APP_ID_B); - private static final int PID_1 = 400; - private static final int PID_2 = 401; - private static final int PID_3 = 402; + private static final String PKG_NAME_A = "name.is.A,pkg.A"; + + @BeforeClass + public static void registerLocalServices() { + addLocalServiceMock(PowerManagerInternal.class); + addLocalServiceMock(DeviceIdleController.LocalService.class); + final UsageStatsManagerInternal usageStats = + addLocalServiceMock(UsageStatsManagerInternal.class); + when(usageStats.getIdleUidsForUser(anyInt())).thenReturn(new int[]{}); + } - public void _setUp() throws Exception { - super.setUp(); + @Before + public void callSystemReady() throws Exception { + MockitoAnnotations.initMocks(this); + + final Context context = InstrumentationRegistry.getContext(); setCurrentTimeMillis(TEST_START); // intercept various broadcasts, and pretend that uids have packages - mServiceContext = new BroadcastInterceptingContext(getContext()) { + mServiceContext = new BroadcastInterceptingContext(context) { @Override public PackageManager getPackageManager() { - return new MockPackageManager() { - @Override - public String[] getPackagesForUid(int uid) { - return new String[] { "com.example" }; - } - - @Override - public PackageInfo getPackageInfo(String packageName, int flags) { - final PackageInfo info = new PackageInfo(); - final Signature signature; - if ("android".equals(packageName)) { - signature = new Signature("F00D"); - } else { - signature = new Signature("DEAD"); - } - info.signatures = new Signature[] { signature }; - return info; - } - - }; + return mPackageManager; } @Override @@ -181,275 +187,112 @@ public class NetworkPolicyManagerServiceTest extends AndroidTestCase { } }; - mPolicyDir = getContext().getFilesDir(); + mPolicyDir = context.getFilesDir(); if (mPolicyDir.exists()) { IoUtils.deleteContents(mPolicyDir); } - mActivityManager = createMock(IActivityManager.class); - mPowerManager = createMock(IPowerManager.class); - mStatsService = createMock(INetworkStatsService.class); - mNetworkManager = createMock(INetworkManagementService.class); - mPolicyListener = createMock(INetworkPolicyListener.class); - mTime = createMock(TrustedTime.class); - mConnManager = createMock(IConnectivityManager.class); - mNotifManager = createMock(INotificationManager.class); - - mService = new NetworkPolicyManagerService(mServiceContext, mActivityManager, mPowerManager, - mStatsService, mNetworkManager, mTime, mPolicyDir, true); + doAnswer(new Answer<Void>() { + + @Override + public Void answer(InvocationOnMock invocation) throws Throwable { + mUidObserver = (IUidObserver) invocation.getArguments()[0]; + Log.d(TAG, "set mUidObserver to " + mUidObserver); + return null; + } + }).when(mActivityManager).registerUidObserver(any(), anyInt()); + + mService = new NetworkPolicyManagerService(mServiceContext, mActivityManager, mStatsService, + mNetworkManager, mTime, mPolicyDir, true); mService.bindConnectivityManager(mConnManager); mService.bindNotificationManager(mNotifManager); + mPolicyListener = new NetworkPolicyListenerAnswer(mService); - // RemoteCallbackList needs a binder to use as key - expect(mPolicyListener.asBinder()).andReturn(mStubBinder).atLeastOnce(); - replay(); - mService.registerListener(mPolicyListener); - verifyAndReset(); + // Sets some common expectations. + when(mPackageManager.getPackageInfo(anyString(), anyInt())).thenAnswer( + new Answer<PackageInfo>() { - // catch IProcessObserver during systemReady() - final Capture<IProcessObserver> processObserver = new Capture<IProcessObserver>(); - mActivityManager.registerProcessObserver(capture(processObserver)); - expectLastCall().atLeastOnce(); - - // catch INetworkManagementEventObserver during systemReady() - final Capture<INetworkManagementEventObserver> networkObserver = new Capture< - INetworkManagementEventObserver>(); - mNetworkManager.registerObserver(capture(networkObserver)); - expectLastCall().atLeastOnce(); - - // expect to answer screen status during systemReady() - expect(mPowerManager.isInteractive()).andReturn(true).atLeastOnce(); - expect(mNetworkManager.isBandwidthControlEnabled()).andReturn(true).atLeastOnce(); + @Override + public PackageInfo answer(InvocationOnMock invocation) throws Throwable { + final String packageName = (String) invocation.getArguments()[0]; + final PackageInfo info = new PackageInfo(); + final Signature signature; + if ("android".equals(packageName)) { + signature = new Signature("F00D"); + } else { + signature = new Signature("DEAD"); + } + info.signatures = new Signature[] { + signature + }; + return info; + } + }); + when(mPackageManager.getApplicationInfoAsUser(anyString(), anyInt(), anyInt())) + .thenReturn(new ApplicationInfo()); + when(mPackageManager.getPackagesForUid(UID_A)).thenReturn(new String[] {PKG_NAME_A}); + when(mNetworkManager.isBandwidthControlEnabled()).thenReturn(true); expectCurrentTime(); - replay(); + // Prepare NPMS. mService.systemReady(); - verifyAndReset(); - mProcessObserver = processObserver.getValue(); + // catch INetworkManagementEventObserver during systemReady() + ArgumentCaptor<INetworkManagementEventObserver> networkObserver = + ArgumentCaptor.forClass(INetworkManagementEventObserver.class); + verify(mNetworkManager).registerObserver(networkObserver.capture()); mNetworkObserver = networkObserver.getValue(); - } - public void _tearDown() throws Exception { + @After + public void removeFiles() throws Exception { for (File file : mPolicyDir.listFiles()) { file.delete(); } + } - mServiceContext = null; - mPolicyDir = null; - - mActivityManager = null; - mPowerManager = null; - mStatsService = null; - mPolicyListener = null; - mTime = null; - - mService = null; - mProcessObserver = null; - - super.tearDown(); + @After + public void unregisterLocalServices() throws Exception { + // Registered by NetworkPolicyManagerService's constructor. + LocalServices.removeServiceForTest(NetworkPolicyManagerInternal.class); } - @Suppress - public void testPolicyChangeTriggersBroadcast() throws Exception { - mService.setUidPolicy(APP_ID_A, POLICY_NONE); + // NOTE: testPolicyChangeTriggersListener() and testUidForeground() are too superficial, they + // don't check for side-effects (like calls to NetworkManagementService) neither cover all + // different modes (Data Saver, Battery Saver, Doze, App idle, etc...). + // These scenarios are extensively tested on CTS' HostsideRestrictBackgroundNetworkTests. - // change background policy and expect broadcast - final Future<Intent> backgroundChanged = mServiceContext.nextBroadcastIntent( - ConnectivityManager.ACTION_BACKGROUND_DATA_SETTING_CHANGED); + @Test + public void testPolicyChangeTriggersListener() throws Exception { + mPolicyListener.expect().onRestrictBackgroundBlacklistChanged(anyInt(), anyBoolean()); + mService.setUidPolicy(APP_ID_A, POLICY_NONE); mService.setUidPolicy(APP_ID_A, POLICY_REJECT_METERED_BACKGROUND); - backgroundChanged.get(); + mPolicyListener.waitAndVerify().onRestrictBackgroundBlacklistChanged(APP_ID_A, true); } - @Suppress - public void testPidForegroundCombined() throws Exception { - IdleFuture idle; - - // push all uid into background - idle = expectIdle(); - mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, false); - mProcessObserver.onForegroundActivitiesChanged(PID_2, UID_A, false); - mProcessObserver.onForegroundActivitiesChanged(PID_3, UID_B, false); - idle.get(); + @Test + public void testUidForeground() throws Exception { + // push all uids into background + mUidObserver.onUidStateChanged(UID_A, ActivityManager.PROCESS_STATE_SERVICE); + mUidObserver.onUidStateChanged(UID_B, ActivityManager.PROCESS_STATE_SERVICE); assertFalse(mService.isUidForeground(UID_A)); assertFalse(mService.isUidForeground(UID_B)); - // push one of the shared pids into foreground - idle = expectIdle(); - mProcessObserver.onForegroundActivitiesChanged(PID_2, UID_A, true); - idle.get(); + // push one of the uids into foreground + mUidObserver.onUidStateChanged(UID_A, ActivityManager.PROCESS_STATE_TOP); assertTrue(mService.isUidForeground(UID_A)); assertFalse(mService.isUidForeground(UID_B)); // and swap another uid into foreground - idle = expectIdle(); - mProcessObserver.onForegroundActivitiesChanged(PID_2, UID_A, false); - mProcessObserver.onForegroundActivitiesChanged(PID_3, UID_B, true); - idle.get(); + mUidObserver.onUidStateChanged(UID_A, ActivityManager.PROCESS_STATE_SERVICE); + mUidObserver.onUidStateChanged(UID_B, ActivityManager.PROCESS_STATE_TOP); assertFalse(mService.isUidForeground(UID_A)); assertTrue(mService.isUidForeground(UID_B)); - - // push both pid into foreground - idle = expectIdle(); - mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, true); - mProcessObserver.onForegroundActivitiesChanged(PID_2, UID_A, true); - idle.get(); - assertTrue(mService.isUidForeground(UID_A)); - - // pull one out, should still be foreground - idle = expectIdle(); - mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, false); - idle.get(); - assertTrue(mService.isUidForeground(UID_A)); - - // pull final pid out, should now be background - idle = expectIdle(); - mProcessObserver.onForegroundActivitiesChanged(PID_2, UID_A, false); - idle.get(); - assertFalse(mService.isUidForeground(UID_A)); - } - - @Suppress - public void testScreenChangesRules() throws Exception { - Future<Void> future; - - expectSetUidMeteredNetworkBlacklist(UID_A, false); - expectSetUidForeground(UID_A, true); - future = expectRulesChanged(UID_A, RULE_ALLOW_ALL); - replay(); - mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, true); - future.get(); - verifyAndReset(); - - // push strict policy for foreground uid, verify ALLOW rule - expectSetUidMeteredNetworkBlacklist(UID_A, false); - expectSetUidForeground(UID_A, true); - future = expectRulesChanged(UID_A, RULE_ALLOW_ALL); - replay(); - mService.setUidPolicy(APP_ID_A, POLICY_REJECT_METERED_BACKGROUND); - future.get(); - verifyAndReset(); - - // now turn screen off and verify REJECT rule - expect(mPowerManager.isInteractive()).andReturn(false).atLeastOnce(); - expectSetUidMeteredNetworkBlacklist(UID_A, true); - expectSetUidForeground(UID_A, false); - future = expectRulesChanged(UID_A, RULE_REJECT_METERED); - replay(); - mServiceContext.sendBroadcast(new Intent(Intent.ACTION_SCREEN_OFF)); - future.get(); - verifyAndReset(); - - // and turn screen back on, verify ALLOW rule restored - expect(mPowerManager.isInteractive()).andReturn(true).atLeastOnce(); - expectSetUidMeteredNetworkBlacklist(UID_A, false); - expectSetUidForeground(UID_A, true); - future = expectRulesChanged(UID_A, RULE_ALLOW_ALL); - replay(); - mServiceContext.sendBroadcast(new Intent(Intent.ACTION_SCREEN_ON)); - future.get(); - verifyAndReset(); - } - - @Suppress - public void testPolicyNone() throws Exception { - Future<Void> future; - - expectSetUidMeteredNetworkBlacklist(UID_A, false); - expectSetUidForeground(UID_A, true); - future = expectRulesChanged(UID_A, RULE_ALLOW_ALL); - replay(); - mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, true); - future.get(); - verifyAndReset(); - - // POLICY_NONE should RULE_ALLOW in foreground - expectSetUidMeteredNetworkBlacklist(UID_A, false); - expectSetUidForeground(UID_A, true); - future = expectRulesChanged(UID_A, RULE_ALLOW_ALL); - replay(); - mService.setUidPolicy(APP_ID_A, POLICY_NONE); - future.get(); - verifyAndReset(); - - // POLICY_NONE should RULE_ALLOW in background - expectSetUidMeteredNetworkBlacklist(UID_A, false); - expectSetUidForeground(UID_A, false); - future = expectRulesChanged(UID_A, RULE_ALLOW_ALL); - replay(); - mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, false); - future.get(); - verifyAndReset(); - } - - @Suppress - public void testPolicyReject() throws Exception { - Future<Void> future; - - // POLICY_REJECT should RULE_ALLOW in background - expectSetUidMeteredNetworkBlacklist(UID_A, true); - expectSetUidForeground(UID_A, false); - future = expectRulesChanged(UID_A, RULE_REJECT_METERED); - replay(); - mService.setUidPolicy(APP_ID_A, POLICY_REJECT_METERED_BACKGROUND); - future.get(); - verifyAndReset(); - - // POLICY_REJECT should RULE_ALLOW in foreground - expectSetUidMeteredNetworkBlacklist(UID_A, false); - expectSetUidForeground(UID_A, true); - future = expectRulesChanged(UID_A, RULE_ALLOW_ALL); - replay(); - mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, true); - future.get(); - verifyAndReset(); - - // POLICY_REJECT should RULE_REJECT in background - expectSetUidMeteredNetworkBlacklist(UID_A, true); - expectSetUidForeground(UID_A, false); - future = expectRulesChanged(UID_A, RULE_REJECT_METERED); - replay(); - mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, false); - future.get(); - verifyAndReset(); - } - - @Suppress - public void testPolicyRejectAddRemove() throws Exception { - Future<Void> future; - - // POLICY_NONE should have RULE_ALLOW in background - expectSetUidMeteredNetworkBlacklist(UID_A, false); - expectSetUidForeground(UID_A, false); - future = expectRulesChanged(UID_A, RULE_ALLOW_ALL); - replay(); - mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, false); - mService.setUidPolicy(APP_ID_A, POLICY_NONE); - future.get(); - verifyAndReset(); - - // adding POLICY_REJECT should cause RULE_REJECT - expectSetUidMeteredNetworkBlacklist(UID_A, true); - expectSetUidForeground(UID_A, false); - future = expectRulesChanged(UID_A, RULE_REJECT_METERED); - replay(); - mService.setUidPolicy(APP_ID_A, POLICY_REJECT_METERED_BACKGROUND); - future.get(); - verifyAndReset(); - - // removing POLICY_REJECT should return us to RULE_ALLOW - expectSetUidMeteredNetworkBlacklist(UID_A, false); - expectSetUidForeground(UID_A, false); - future = expectRulesChanged(UID_A, RULE_ALLOW_ALL); - replay(); - mService.setUidPolicy(APP_ID_A, POLICY_NONE); - future.get(); - verifyAndReset(); } + @Test public void testLastCycleBoundaryThisMonth() throws Exception { // assume cycle day of "5th", which should be in same month final long currentTime = parseTime("2007-11-14T00:00:00.000Z"); @@ -461,6 +304,7 @@ public class NetworkPolicyManagerServiceTest extends AndroidTestCase { assertTimeEquals(expectedCycle, actualCycle); } + @Test public void testLastCycleBoundaryLastMonth() throws Exception { // assume cycle day of "20th", which should be in last month final long currentTime = parseTime("2007-11-14T00:00:00.000Z"); @@ -472,6 +316,7 @@ public class NetworkPolicyManagerServiceTest extends AndroidTestCase { assertTimeEquals(expectedCycle, actualCycle); } + @Test public void testLastCycleBoundaryThisMonthFebruary() throws Exception { // assume cycle day of "30th" in february; should go to january final long currentTime = parseTime("2007-02-14T00:00:00.000Z"); @@ -483,6 +328,7 @@ public class NetworkPolicyManagerServiceTest extends AndroidTestCase { assertTimeEquals(expectedCycle, actualCycle); } + @Test public void testLastCycleBoundaryLastMonthFebruary() throws Exception { // assume cycle day of "30th" in february, which should clamp final long currentTime = parseTime("2007-03-14T00:00:00.000Z"); @@ -494,6 +340,7 @@ public class NetworkPolicyManagerServiceTest extends AndroidTestCase { assertTimeEquals(expectedCycle, actualCycle); } + @Test public void testCycleBoundaryLeapYear() throws Exception { final NetworkPolicy policy = new NetworkPolicy( sTemplateWifi, 29, TIMEZONE_UTC, 1024L, 1024L, false); @@ -517,6 +364,7 @@ public class NetworkPolicyManagerServiceTest extends AndroidTestCase { computeNextCycleBoundary(parseTime("2007-03-14T00:00:00.000Z"), policy)); } + @Test public void testNextCycleTimezoneAfterUtc() throws Exception { // US/Central is UTC-6 final NetworkPolicy policy = new NetworkPolicy( @@ -525,6 +373,7 @@ public class NetworkPolicyManagerServiceTest extends AndroidTestCase { computeNextCycleBoundary(parseTime("2012-01-05T00:00:00.000Z"), policy)); } + @Test public void testNextCycleTimezoneBeforeUtc() throws Exception { // Israel is UTC+2 final NetworkPolicy policy = new NetworkPolicy( @@ -533,6 +382,7 @@ public class NetworkPolicyManagerServiceTest extends AndroidTestCase { computeNextCycleBoundary(parseTime("2012-01-05T00:00:00.000Z"), policy)); } + @Test public void testNextCycleSane() throws Exception { final NetworkPolicy policy = new NetworkPolicy( sTemplateWifi, 31, TIMEZONE_UTC, WARNING_DISABLED, LIMIT_DISABLED, false); @@ -548,6 +398,7 @@ public class NetworkPolicyManagerServiceTest extends AndroidTestCase { } } + @Test public void testLastCycleSane() throws Exception { final NetworkPolicy policy = new NetworkPolicy( sTemplateWifi, 31, TIMEZONE_UTC, WARNING_DISABLED, LIMIT_DISABLED, false); @@ -563,6 +414,7 @@ public class NetworkPolicyManagerServiceTest extends AndroidTestCase { } } + @Test public void testCycleTodayJanuary() throws Exception { final NetworkPolicy policy = new NetworkPolicy( sTemplateWifi, 14, "US/Pacific", 1024L, 1024L, false); @@ -582,6 +434,7 @@ public class NetworkPolicyManagerServiceTest extends AndroidTestCase { computeLastCycleBoundary(parseTime("2013-01-14T15:11:00.000-08:00"), policy)); } + @Test public void testLastCycleBoundaryDST() throws Exception { final long currentTime = parseTime("1989-01-02T07:30:00.000"); final long expectedCycle = parseTime("1988-12-03T02:00:00.000Z"); @@ -592,11 +445,10 @@ public class NetworkPolicyManagerServiceTest extends AndroidTestCase { assertTimeEquals(expectedCycle, actualCycle); } - @Suppress + @Test public void testNetworkPolicyAppliedCycleLastMonth() throws Exception { NetworkState[] state = null; NetworkStats stats = null; - Future<Void> future; final long TIME_FEB_15 = 1171497600000L; final long TIME_MAR_10 = 1173484800000L; @@ -607,75 +459,40 @@ public class NetworkPolicyManagerServiceTest extends AndroidTestCase { // first, pretend that wifi network comes online. no policy active, // which means we shouldn't push limit to interface. state = new NetworkState[] { buildWifi() }; - expect(mConnManager.getAllNetworkState()).andReturn(state).atLeastOnce(); + when(mConnManager.getAllNetworkState()).thenReturn(state); expectCurrentTime(); - expectClearNotifications(); - expectAdvisePersistThreshold(); - future = expectMeteredIfacesChanged(); - replay(); + mPolicyListener.expect().onMeteredIfacesChanged(any()); mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION)); - future.get(); - verifyAndReset(); + mPolicyListener.waitAndVerify().onMeteredIfacesChanged(any()); // now change cycle to be on 15th, and test in early march, to verify we // pick cycle day in previous month. - expect(mConnManager.getAllNetworkState()).andReturn(state).atLeastOnce(); + when(mConnManager.getAllNetworkState()).thenReturn(state); expectCurrentTime(); // pretend that 512 bytes total have happened stats = new NetworkStats(getElapsedRealtime(), 1) .addIfaceValues(TEST_IFACE, 256L, 2L, 256L, 2L); - expect(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15, TIME_MAR_10)) - .andReturn(stats.getTotalBytes()).atLeastOnce(); - expectPolicyDataEnable(TYPE_WIFI, true); - - // TODO: consider making strongly ordered mock - expectRemoveInterfaceQuota(TEST_IFACE); - expectSetInterfaceQuota(TEST_IFACE, (2 * MB_IN_BYTES) - 512); - - expectClearNotifications(); - expectAdvisePersistThreshold(); - future = expectMeteredIfacesChanged(TEST_IFACE); + when(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15, TIME_MAR_10)) + .thenReturn(stats.getTotalBytes()); - replay(); + mPolicyListener.expect().onMeteredIfacesChanged(any()); setNetworkPolicies(new NetworkPolicy( sTemplateWifi, CYCLE_DAY, TIMEZONE_UTC, 1 * MB_IN_BYTES, 2 * MB_IN_BYTES, false)); - future.get(); - verifyAndReset(); - } - - @Suppress - public void testUidRemovedPolicyCleared() throws Exception { - Future<Void> future; + mPolicyListener.waitAndVerify().onMeteredIfacesChanged(eq(new String[]{TEST_IFACE})); - // POLICY_REJECT should RULE_REJECT in background - expectSetUidMeteredNetworkBlacklist(UID_A, true); - expectSetUidForeground(UID_A, false); - future = expectRulesChanged(UID_A, RULE_REJECT_METERED); - replay(); - mService.setUidPolicy(APP_ID_A, POLICY_REJECT_METERED_BACKGROUND); - future.get(); - verifyAndReset(); - - // uninstall should clear RULE_REJECT - expectSetUidMeteredNetworkBlacklist(UID_A, false); - expectSetUidForeground(UID_A, false); - future = expectRulesChanged(UID_A, RULE_ALLOW_ALL); - replay(); - final Intent intent = new Intent(ACTION_UID_REMOVED); - intent.putExtra(EXTRA_UID, UID_A); - mServiceContext.sendBroadcast(intent); - future.get(); - verifyAndReset(); + // TODO: consider making strongly ordered mock + verifyPolicyDataEnable(TYPE_WIFI, true); + verifyRemoveInterfaceQuota(TEST_IFACE); + verifySetInterfaceQuota(TEST_IFACE, (2 * MB_IN_BYTES) - 512); } - @Suppress + @Test public void testOverWarningLimitNotification() throws Exception { NetworkState[] state = null; NetworkStats stats = null; - Future<Void> future; - Future<String> tagFuture; + Future<String> tagFuture = null; final long TIME_FEB_15 = 1171497600000L; final long TIME_MAR_10 = 1173484800000L; @@ -690,20 +507,15 @@ public class NetworkPolicyManagerServiceTest extends AndroidTestCase { { expectCurrentTime(); - expect(mConnManager.getAllNetworkState()).andReturn(state).atLeastOnce(); - expect(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15, currentTimeMillis())) - .andReturn(stats.getTotalBytes()).atLeastOnce(); - expectPolicyDataEnable(TYPE_WIFI, true); - - expectClearNotifications(); - expectAdvisePersistThreshold(); - future = expectMeteredIfacesChanged(); + when(mConnManager.getAllNetworkState()).thenReturn(state); + when(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15, + currentTimeMillis())).thenReturn(stats.getTotalBytes()); - replay(); + mPolicyListener.expect().onMeteredIfacesChanged(any()); setNetworkPolicies(new NetworkPolicy(sTemplateWifi, CYCLE_DAY, TIMEZONE_UTC, 1 * MB_IN_BYTES, 2 * MB_IN_BYTES, false)); - future.get(); - verifyAndReset(); + mPolicyListener.waitAndVerify().onMeteredIfacesChanged(any()); + verifyPolicyDataEnable(TYPE_WIFI, true); } // bring up wifi network @@ -714,22 +526,17 @@ public class NetworkPolicyManagerServiceTest extends AndroidTestCase { { expectCurrentTime(); - expect(mConnManager.getAllNetworkState()).andReturn(state).atLeastOnce(); - expect(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15, currentTimeMillis())) - .andReturn(stats.getTotalBytes()).atLeastOnce(); - expectPolicyDataEnable(TYPE_WIFI, true); + when(mConnManager.getAllNetworkState()).thenReturn(state); + when(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15, + currentTimeMillis())).thenReturn(stats.getTotalBytes()); - expectRemoveInterfaceQuota(TEST_IFACE); - expectSetInterfaceQuota(TEST_IFACE, 2 * MB_IN_BYTES); - - expectClearNotifications(); - expectAdvisePersistThreshold(); - future = expectMeteredIfacesChanged(TEST_IFACE); - - replay(); + mPolicyListener.expect().onMeteredIfacesChanged(any()); mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION)); - future.get(); - verifyAndReset(); + mPolicyListener.waitAndVerify().onMeteredIfacesChanged(eq(new String[]{TEST_IFACE})); + + verifyPolicyDataEnable(TYPE_WIFI, true); + verifyRemoveInterfaceQuota(TEST_IFACE); + verifySetInterfaceQuota(TEST_IFACE, 2 * MB_IN_BYTES); } // go over warning, which should kick notification @@ -739,18 +546,15 @@ public class NetworkPolicyManagerServiceTest extends AndroidTestCase { { expectCurrentTime(); - expect(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15, currentTimeMillis())) - .andReturn(stats.getTotalBytes()).atLeastOnce(); - expectPolicyDataEnable(TYPE_WIFI, true); - - expectForceUpdate(); - expectClearNotifications(); + when(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15, + currentTimeMillis())).thenReturn(stats.getTotalBytes()); tagFuture = expectEnqueueNotification(); - replay(); mNetworkObserver.limitReached(null, TEST_IFACE); + assertNotificationType(TYPE_WARNING, tagFuture.get()); - verifyAndReset(); + verifyPolicyDataEnable(TYPE_WIFI, true); + } // go over limit, which should kick notification and dialog @@ -760,18 +564,14 @@ public class NetworkPolicyManagerServiceTest extends AndroidTestCase { { expectCurrentTime(); - expect(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15, currentTimeMillis())) - .andReturn(stats.getTotalBytes()).atLeastOnce(); - expectPolicyDataEnable(TYPE_WIFI, false); - - expectForceUpdate(); - expectClearNotifications(); + when(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15, + currentTimeMillis())).thenReturn(stats.getTotalBytes()); tagFuture = expectEnqueueNotification(); - replay(); mNetworkObserver.limitReached(null, TEST_IFACE); + assertNotificationType(TYPE_LIMIT, tagFuture.get()); - verifyAndReset(); + verifyPolicyDataEnable(TYPE_WIFI, false); } // now snooze policy, which should remove quota @@ -779,35 +579,28 @@ public class NetworkPolicyManagerServiceTest extends AndroidTestCase { { expectCurrentTime(); - expect(mConnManager.getAllNetworkState()).andReturn(state).atLeastOnce(); - expect(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15, currentTimeMillis())) - .andReturn(stats.getTotalBytes()).atLeastOnce(); - expectPolicyDataEnable(TYPE_WIFI, true); - - // snoozed interface still has high quota so background data is - // still restricted. - expectRemoveInterfaceQuota(TEST_IFACE); - expectSetInterfaceQuota(TEST_IFACE, Long.MAX_VALUE); - expectAdvisePersistThreshold(); - expectMeteredIfacesChanged(TEST_IFACE); - - future = expectClearNotifications(); + when(mConnManager.getAllNetworkState()).thenReturn(state); + when(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15, + currentTimeMillis())).thenReturn(stats.getTotalBytes()); tagFuture = expectEnqueueNotification(); - replay(); + mPolicyListener.expect().onMeteredIfacesChanged(any()); mService.snoozeLimit(sTemplateWifi); + mPolicyListener.waitAndVerify().onMeteredIfacesChanged(eq(new String[]{TEST_IFACE})); + assertNotificationType(TYPE_LIMIT_SNOOZED, tagFuture.get()); - future.get(); - verifyAndReset(); + // snoozed interface still has high quota so background data is + // still restricted. + verifyRemoveInterfaceQuota(TEST_IFACE); + verifySetInterfaceQuota(TEST_IFACE, Long.MAX_VALUE); + verifyPolicyDataEnable(TYPE_WIFI, true); } } - @Suppress + @Test public void testMeteredNetworkWithoutLimit() throws Exception { NetworkState[] state = null; NetworkStats stats = null; - Future<Void> future; - Future<String> tagFuture; final long TIME_FEB_15 = 1171497600000L; final long TIME_MAR_10 = 1173484800000L; @@ -822,24 +615,19 @@ public class NetworkPolicyManagerServiceTest extends AndroidTestCase { { expectCurrentTime(); - expect(mConnManager.getAllNetworkState()).andReturn(state).atLeastOnce(); - expect(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15, currentTimeMillis())) - .andReturn(stats.getTotalBytes()).atLeastOnce(); - expectPolicyDataEnable(TYPE_WIFI, true); - - expectRemoveInterfaceQuota(TEST_IFACE); - expectSetInterfaceQuota(TEST_IFACE, Long.MAX_VALUE); - - expectClearNotifications(); - expectAdvisePersistThreshold(); - future = expectMeteredIfacesChanged(TEST_IFACE); + when(mConnManager.getAllNetworkState()).thenReturn(state); + when(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15, + currentTimeMillis())).thenReturn(stats.getTotalBytes()); - replay(); + mPolicyListener.expect().onMeteredIfacesChanged(any()); setNetworkPolicies(new NetworkPolicy( sTemplateWifi, CYCLE_DAY, TIMEZONE_UTC, WARNING_DISABLED, LIMIT_DISABLED, true)); - future.get(); - verifyAndReset(); + mPolicyListener.waitAndVerify().onMeteredIfacesChanged(eq(new String[]{TEST_IFACE})); + + verifyPolicyDataEnable(TYPE_WIFI, true); + verifyRemoveInterfaceQuota(TEST_IFACE); + verifySetInterfaceQuota(TEST_IFACE, Long.MAX_VALUE); } } @@ -862,87 +650,36 @@ public class NetworkPolicyManagerServiceTest extends AndroidTestCase { } private void expectCurrentTime() throws Exception { - expect(mTime.forceRefresh()).andReturn(false).anyTimes(); - expect(mTime.hasCache()).andReturn(true).anyTimes(); - expect(mTime.currentTimeMillis()).andReturn(currentTimeMillis()).anyTimes(); - expect(mTime.getCacheAge()).andReturn(0L).anyTimes(); - expect(mTime.getCacheCertainty()).andReturn(0L).anyTimes(); - } - - private void expectForceUpdate() throws Exception { - mStatsService.forceUpdate(); - expectLastCall().atLeastOnce(); - } - - private Future<Void> expectClearNotifications() throws Exception { - final FutureAnswer future = new FutureAnswer(); - mNotifManager.cancelNotificationWithTag( - isA(String.class), isA(String.class), anyInt(), anyInt()); - expectLastCall().andAnswer(future).anyTimes(); - return future; + when(mTime.forceRefresh()).thenReturn(false); + when(mTime.hasCache()).thenReturn(true); + when(mTime.currentTimeMillis()).thenReturn(currentTimeMillis()); + when(mTime.getCacheAge()).thenReturn(0L); + when(mTime.getCacheCertainty()).thenReturn(0L); } private Future<String> expectEnqueueNotification() throws Exception { - final FutureCapture<String> tag = new FutureCapture<String>(); - mNotifManager.enqueueNotificationWithTag(isA(String.class), isA(String.class), - capture(tag.capture), anyInt(), - isA(Notification.class), isA(int[].class), UserHandle.myUserId()); - return tag; - } - - private void expectSetInterfaceQuota(String iface, long quotaBytes) throws Exception { - mNetworkManager.setInterfaceQuota(iface, quotaBytes); - expectLastCall().atLeastOnce(); + final FutureAnswer<String> futureAnswer = new FutureAnswer<String>(2); + doAnswer(futureAnswer).when(mNotifManager).enqueueNotificationWithTag( + anyString(), anyString(), anyString() /* capture here (index 2)*/, + anyInt(), isA(Notification.class), isA(int[].class), anyInt()); + return futureAnswer; } - private void expectRemoveInterfaceQuota(String iface) throws Exception { - mNetworkManager.removeInterfaceQuota(iface); - expectLastCall().atLeastOnce(); + private void verifySetInterfaceQuota(String iface, long quotaBytes) throws Exception { + verify(mNetworkManager, atLeastOnce()).setInterfaceQuota(iface, quotaBytes); } - private void expectSetInterfaceAlert(String iface, long alertBytes) throws Exception { - mNetworkManager.setInterfaceAlert(iface, alertBytes); - expectLastCall().atLeastOnce(); + private void verifyRemoveInterfaceQuota(String iface) throws Exception { + verify(mNetworkManager, atLeastOnce()).removeInterfaceQuota(iface); } - private void expectRemoveInterfaceAlert(String iface) throws Exception { - mNetworkManager.removeInterfaceAlert(iface); - expectLastCall().atLeastOnce(); - } - - private void expectSetUidMeteredNetworkBlacklist(int uid, boolean rejectOnQuotaInterfaces) - throws Exception { - mNetworkManager.setUidMeteredNetworkBlacklist(uid, rejectOnQuotaInterfaces); - expectLastCall().atLeastOnce(); - } - - private void expectSetUidForeground(int uid, boolean uidForeground) throws Exception { - mStatsService.setUidForeground(uid, uidForeground); - expectLastCall().atLeastOnce(); - } - - private Future<Void> expectRulesChanged(int uid, int policy) throws Exception { - final FutureAnswer future = new FutureAnswer(); - mPolicyListener.onUidRulesChanged(eq(uid), eq(policy)); - expectLastCall().andAnswer(future); - return future; - } - - private Future<Void> expectMeteredIfacesChanged(String... ifaces) throws Exception { - final FutureAnswer future = new FutureAnswer(); - mPolicyListener.onMeteredIfacesChanged(aryEq(ifaces)); - expectLastCall().andAnswer(future); - return future; - } - - private Future<Void> expectPolicyDataEnable(int type, boolean enabled) throws Exception { + private Future<Void> verifyPolicyDataEnable(int type, boolean enabled) throws Exception { // TODO: bring back this test return null; } - private void expectAdvisePersistThreshold() throws Exception { - mStatsService.advisePersistThreshold(anyLong()); - expectLastCall().anyTimes(); + private void verifyAdvisePersistThreshold() throws Exception { + verify(mStatsService).advisePersistThreshold(anyLong()); } private static class TestAbstractFuture<T> extends AbstractFuture<T> { @@ -956,50 +693,21 @@ public class NetworkPolicyManagerServiceTest extends AndroidTestCase { } } - private static class FutureAnswer extends TestAbstractFuture<Void> implements IAnswer<Void> { - @Override - public Void answer() { - set(null); - return null; - } - } - - private static class FutureCapture<T> extends TestAbstractFuture<T> { - public Capture<T> capture = new Capture<T>() { - @Override - public void setValue(T value) { - super.setValue(value); - set(value); - } - }; - } + private static class FutureAnswer<T> extends TestAbstractFuture<T> implements Answer<Void> { + private final int index; - private static class IdleFuture extends AbstractFuture<Void> implements IdleHandler { - @Override - public Void get() throws InterruptedException, ExecutionException { - try { - return get(5, TimeUnit.SECONDS); - } catch (TimeoutException e) { - throw new RuntimeException(e); - } + FutureAnswer(int index) { + this.index = index; } - @Override - public boolean queueIdle() { - set(null); - return false; + public Void answer(InvocationOnMock invocation) throws Throwable { + @SuppressWarnings("unchecked") + T captured = (T) invocation.getArguments()[index]; + set(captured); + return null; } } - /** - * Wait until {@link #mService} internal {@link Handler} is idle. - */ - private IdleFuture expectIdle() { - final IdleFuture future = new IdleFuture(); - mService.addIdleHandler(future); - return future; - } - private static void assertTimeEquals(long expected, long actual) { if (expected != actual) { fail("expected " + formatTime(expected) + " but was actually " + formatTime(actual)); @@ -1027,7 +735,7 @@ public class NetworkPolicyManagerServiceTest extends AndroidTestCase { } private static void assertNotificationType(int expected, String actualTag) { - assertEquals( + assertEquals("notification type mismatch for '" + actualTag +"'", Integer.toString(expected), actualTag.substring(actualTag.lastIndexOf(':') + 1)); } @@ -1048,15 +756,59 @@ public class NetworkPolicyManagerServiceTest extends AndroidTestCase { mElapsedRealtime += duration; } - private void replay() { - EasyMock.replay(mActivityManager, mPowerManager, mStatsService, mPolicyListener, - mNetworkManager, mTime, mConnManager, mNotifManager); + /** + * Creates a mock and registers it to {@link LocalServices}. + */ + private static <T> T addLocalServiceMock(Class<T> clazz) { + final T mock = mock(clazz); + LocalServices.addService(clazz, mock); + return mock; } - private void verifyAndReset() { - EasyMock.verify(mActivityManager, mPowerManager, mStatsService, mPolicyListener, - mNetworkManager, mTime, mConnManager, mNotifManager); - EasyMock.reset(mActivityManager, mPowerManager, mStatsService, mPolicyListener, - mNetworkManager, mTime, mConnManager, mNotifManager); + /** + * Custom Mockito answer used to verify async {@link INetworkPolicyListener} calls. + * + * <p>Typical usage: + * <pre><code> + * mPolicyListener.expect().someCallback(any()); + * // do something on objects under test + * mPolicyListener.waitAndVerify().someCallback(eq(expectedValue)); + * </code></pre> + */ + final class NetworkPolicyListenerAnswer implements Answer<Void> { + private CountDownLatch latch; + private final INetworkPolicyListener listener; + + NetworkPolicyListenerAnswer(NetworkPolicyManagerService service) { + this.listener = mock(INetworkPolicyListener.class); + // RemoteCallbackList needs a binder to use as key + when(listener.asBinder()).thenReturn(new Binder()); + service.registerListener(listener); + } + + @Override + public Void answer(InvocationOnMock invocation) throws Throwable { + Log.d(TAG,"counting down on answer: " + invocation); + latch.countDown(); + return null; + } + + INetworkPolicyListener expect() { + assertNull("expect() called before waitAndVerify()", latch); + latch = new CountDownLatch(1); + return doAnswer(this).when(listener); + } + + INetworkPolicyListener waitAndVerify() { + assertNotNull("waitAndVerify() called before expect()", latch); + try { + assertTrue("callback not called in 5 seconds", latch.await(5, TimeUnit.SECONDS)); + } catch (InterruptedException e) { + fail("Thread interrupted before callback called"); + } finally { + latch = null; + } + return verify(listener, atLeastOnce()); + } } } diff --git a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java index e7f33457bb5f..1c7a138468cf 100644 --- a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java +++ b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java @@ -247,20 +247,6 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase { } @Override - protected boolean isUserUnlockedL(@UserIdInt int userId) { - // Note due to a late change, now ShortcutManager doesn't use - // UserManager.isUserUnlockingOrUnlocked(). But all unit tests are still using it, - // so we convert here. - - final long token = injectClearCallingIdentity(); - try { - return mMockUserManager.isUserUnlockingOrUnlocked(userId); - } finally { - injectRestoreCallingIdentity(token); - } - } - - @Override int injectDipToPixel(int dip) { return dip; } diff --git a/services/tests/servicestests/src/com/android/server/pm/KeySetManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/pm/KeySetManagerServiceTest.java index ba83be19bed9..64c562278227 100644 --- a/services/tests/servicestests/src/com/android/server/pm/KeySetManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/pm/KeySetManagerServiceTest.java @@ -39,7 +39,7 @@ public class KeySetManagerServiceTest extends AndroidTestCase { public PackageSetting generateFakePackageSetting(String name) { return new PackageSetting(name, name, new File(mContext.getCacheDir(), "fakeCodePath"), new File(mContext.getCacheDir(), "fakeResPath"), "", "", "", - "", 1, 0, 0, null, null); + "", 1, 0, 0, null, null, 0 /*sharedUserId*/); } @Override diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java b/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java index a9391344c7b4..09bd12c17a74 100644 --- a/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java +++ b/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java @@ -522,7 +522,8 @@ public class PackageManagerSettingsTests { pkgFlags, 0 /*privateFlags*/, null /*parentPackageName*/, - null /*childPackageNames*/); + null /*childPackageNames*/, + 0 /*sharedUserId*/); } private @NonNull List<UserInfo> createFakeUsers() { diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java index 75a34272d82b..253334eec9cf 100644 --- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java +++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java @@ -5863,6 +5863,7 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest { assertEmpty(mManager.getPinnedShortcuts()); }); // Send add broadcast, but the user is not running, so should be ignored. + mService.handleCleanupUser(USER_10); mRunningUsers.put(USER_10, false); mUnlockedUsers.put(USER_10, false); diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java index ad5bc7730833..d25923c019ca 100644 --- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java +++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java @@ -2005,4 +2005,36 @@ public class ShortcutManagerTest2 extends BaseShortcutManagerTest { }); }); } + + public void testIsUserUnlocked() { + mRunningUsers.clear(); + mUnlockedUsers.clear(); + + assertFalse(mService.isUserUnlockedL(USER_0)); + assertFalse(mService.isUserUnlockedL(USER_10)); + + // Start user 0, still locked. + mRunningUsers.put(USER_0, true); + assertFalse(mService.isUserUnlockedL(USER_0)); + assertFalse(mService.isUserUnlockedL(USER_10)); + + // Unlock user. + mUnlockedUsers.put(USER_0, true); + assertTrue(mService.isUserUnlockedL(USER_0)); + assertFalse(mService.isUserUnlockedL(USER_10)); + + // Clear again. + mRunningUsers.clear(); + mUnlockedUsers.clear(); + + // Directly call the lifecycle event. Now also locked. + mService.handleUnlockUser(USER_0); + assertTrue(mService.isUserUnlockedL(USER_0)); + assertFalse(mService.isUserUnlockedL(USER_10)); + + // Directly call the stop lifecycle event. Goes back to the initial state. + mService.handleCleanupUser(USER_0); + assertFalse(mService.isUserUnlockedL(USER_0)); + assertFalse(mService.isUserUnlockedL(USER_10)); + } } diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java index 8560651fa7ec..efd479f394c5 100644 --- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java +++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java @@ -563,6 +563,7 @@ public class UsbDeviceManager { mAccessoryModeRequestTime + ACCESSORY_REQUEST_TIMEOUT; if (mConfigured && enteringAccessoryMode) { + mAccessoryModeRequestTime = 0; // successfully entered accessory mode if (mAccessoryStrings != null) { diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java index b0cc2aca8981..c3075b3daa3e 100644 --- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java +++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java @@ -46,6 +46,7 @@ import android.util.Slog; import android.view.IWindowManager; import android.view.WindowManager; +import com.android.internal.app.AssistUtils; import com.android.internal.app.IAssistScreenshotReceiver; import com.android.internal.app.IVoiceInteractionSessionShowCallback; import com.android.internal.app.IVoiceInteractor; @@ -301,7 +302,7 @@ final class VoiceInteractionSessionConnection implements ServiceConnection { } else { mScreenshot = null; } - if (needDisclosure) { + if (needDisclosure && AssistUtils.shouldDisclose(mContext, mSessionComponentName)) { mHandler.post(mShowAssistDisclosureRunnable); } if (mSession != null) { diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java index 68a61667e976..e666986aae50 100644 --- a/telephony/java/android/telephony/CarrierConfigManager.java +++ b/telephony/java/android/telephony/CarrierConfigManager.java @@ -906,6 +906,19 @@ public class CarrierConfigManager { public static final String KEY_ENHANCED_4G_LTE_TITLE_VARIANT_BOOL = "enhanced_4g_lte_title_variant_bool"; + /** + * Indicates whether the carrier wants to notify the user when handover of an LTE video call to + * WIFI fails. + * <p> + * When {@code true}, if a video call starts on LTE and the modem reports a failure to handover + * the call to WIFI or if no handover success is reported within 60 seconds of call initiation, + * the {@link android.telephony.TelephonyManager#EVENT_HANDOVER_TO_WIFI_FAILED} event is raised + * on the connection. + * @hide + */ + public static final String KEY_NOTIFY_VT_HANDOVER_TO_WIFI_FAILURE_BOOL = + "notify_vt_handover_to_wifi_failure_bool"; + /** The default value for every variable. */ private final static PersistableBundle sDefaults; @@ -1071,6 +1084,7 @@ public class CarrierConfigManager { sDefaults.putStringArray(KEY_IMS_REASONINFO_MAPPING_STRING_ARRAY, null); sDefaults.putBoolean(KEY_ENHANCED_4G_LTE_TITLE_VARIANT_BOOL, false); + sDefaults.putBoolean(KEY_NOTIFY_VT_HANDOVER_TO_WIFI_FAILURE_BOOL, false); } /** diff --git a/telephony/java/android/telephony/DisconnectCause.java b/telephony/java/android/telephony/DisconnectCause.java index d7d4e840aa77..f5e422df7511 100644 --- a/telephony/java/android/telephony/DisconnectCause.java +++ b/telephony/java/android/telephony/DisconnectCause.java @@ -212,6 +212,20 @@ public class DisconnectCause { */ public static final int MAXIMUM_NUMBER_OF_CALLS_REACHED = 53; + /** + * The call was terminated because cellular data has been disabled. + * Used when in a video call and the user disables cellular data via the settings. + * {@hide} + */ + public static final int DATA_DISABLED = 54; + + /** + * The call was terminated because the data policy has disabled cellular data. + * Used when in a video call and the user has exceeded the device data limit. + * {@hide} + */ + public static final int DATA_LIMIT_REACHED = 55; + //********************************************************************************************* // When adding a disconnect type: // 1) Please assign the new type the next id value below. @@ -220,14 +234,14 @@ public class DisconnectCause { // 4) Update toString() with the newly added disconnect type. // 5) Update android.telecom.DisconnectCauseUtil with any mappings to a telecom.DisconnectCause. // - // NextId: 54 + // NextId: 56 //********************************************************************************************* /** Smallest valid value for call disconnect codes. */ public static final int MINIMUM_VALID_VALUE = NOT_DISCONNECTED; /** Largest valid value for call disconnect codes. */ - public static final int MAXIMUM_VALID_VALUE = MAXIMUM_NUMBER_OF_CALLS_REACHED; + public static final int MAXIMUM_VALID_VALUE = DATA_LIMIT_REACHED; /** Private constructor to avoid class instantiation. */ private DisconnectCause() { @@ -343,6 +357,10 @@ public class DisconnectCause { return "ANSWERED_ELSEWHERE"; case MAXIMUM_NUMBER_OF_CALLS_REACHED: return "MAXIMUM_NUMER_OF_CALLS_REACHED"; + case DATA_DISABLED: + return "DATA_DISABLED"; + case DATA_LIMIT_REACHED: + return "DATA_LIMIT_REACHED"; default: return "INVALID: " + cause; } diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java index fed9e71db35a..4138aa09f99a 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -2484,6 +2484,56 @@ public class TelephonyManager { } /** + * Enables or disables the visual voicemail client for a phone account. + * + * <p>Requires that the calling app is the default dialer, or has carrier privileges, or + * has permission {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}. + * @see #hasCarrierPrivileges + * + * @param phoneAccountHandle the phone account to change the client state + * @param enabled the new state of the client + * @hide + */ + @SystemApi + public void setVisualVoicemailEnabled(PhoneAccountHandle phoneAccountHandle, boolean enabled){ + try { + ITelephony telephony = getITelephony(); + if (telephony != null) { + telephony.setVisualVoicemailEnabled(mContext.getOpPackageName(), phoneAccountHandle, + enabled); + } + } catch (RemoteException ex) { + } catch (NullPointerException ex) { + // This could happen before phone restarts due to crashing + } + } + + /** + * Returns whether the visual voicemail client is enabled. + * + * <p>Requires Permission: + * {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE} + * + * @param phoneAccountHandle the phone account to check for. + * @return {@code true} when the visual voicemail client is enabled for this client + * @hide + */ + @SystemApi + public boolean isVisualVoicemailEnabled(PhoneAccountHandle phoneAccountHandle){ + try { + ITelephony telephony = getITelephony(); + if (telephony != null) { + return telephony.isVisualVoicemailEnabled( + mContext.getOpPackageName(), phoneAccountHandle); + } + } catch (RemoteException ex) { + } catch (NullPointerException ex) { + // This could happen before phone restarts due to crashing + } + return false; + } + + /** * Enables the visual voicemail SMS filter for a phone account. When the filter is * enabled, Incoming SMS messages matching the OMTP VVM SMS interface will be redirected to the * visual voicemail client with diff --git a/telephony/java/com/android/ims/ImsReasonInfo.java b/telephony/java/com/android/ims/ImsReasonInfo.java index 408ad31674c4..56b882221cd7 100644 --- a/telephony/java/com/android/ims/ImsReasonInfo.java +++ b/telephony/java/com/android/ims/ImsReasonInfo.java @@ -298,6 +298,16 @@ public class ImsReasonInfo implements Parcelable { public static final int CODE_REMOTE_CALL_DECLINE = 1404; /** + * Indicates the call was disconnected due to the user reaching their data limit. + */ + public static final int CODE_DATA_LIMIT_REACHED = 1405; + + /** + * Indicates the call was disconnected due to the user disabling cellular data. + */ + public static final int CODE_DATA_DISABLED = 1406; + + /** * Network string error messages. * mExtraMessage may have these values. */ diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl index 7e7071ee173a..a8eaf3627013 100644 --- a/telephony/java/com/android/internal/telephony/ITelephony.aidl +++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl @@ -454,6 +454,12 @@ interface ITelephony { */ int getVoiceMessageCountForSubscriber(int subId); + oneway void setVisualVoicemailEnabled(String callingPackage, + in PhoneAccountHandle accountHandle, boolean enabled); + + boolean isVisualVoicemailEnabled(String callingPackage, + in PhoneAccountHandle accountHandle); + // Not oneway, caller needs to make sure the vaule is set before receiving a SMS void enableVisualVoicemailSmsFilter(String callingPackage, int subId, in VisualVoicemailSmsFilterSettings settings); diff --git a/tools/aapt/AaptAssets.cpp b/tools/aapt/AaptAssets.cpp index c1cfd0b5f1e7..3c3edda85e4f 100644 --- a/tools/aapt/AaptAssets.cpp +++ b/tools/aapt/AaptAssets.cpp @@ -1309,8 +1309,8 @@ bail: status_t AaptAssets::filter(Bundle* bundle) { - WeakResourceFilter reqFilter; - status_t err = reqFilter.parse(bundle->getConfigurations()); + sp<WeakResourceFilter> reqFilter(new WeakResourceFilter()); + status_t err = reqFilter->parse(bundle->getConfigurations()); if (err != NO_ERROR) { return err; } @@ -1326,12 +1326,12 @@ status_t AaptAssets::filter(Bundle* bundle) preferredDensity = preferredConfig.density; } - if (reqFilter.isEmpty() && preferredDensity == 0) { + if (reqFilter->isEmpty() && preferredDensity == 0) { return NO_ERROR; } if (bundle->getVerbose()) { - if (!reqFilter.isEmpty()) { + if (!reqFilter->isEmpty()) { printf("Applying required filter: %s\n", bundle->getConfigurations().string()); } @@ -1383,7 +1383,7 @@ status_t AaptAssets::filter(Bundle* bundle) continue; } const ResTable_config& config(file->getGroupEntry().toParams()); - if (!reqFilter.match(config)) { + if (!reqFilter->match(config)) { if (bundle->getVerbose()) { printf("Pruning unneeded resource: %s\n", file->getPrintableSource().string()); diff --git a/tools/aapt/AaptAssets.h b/tools/aapt/AaptAssets.h index 4fdc9640e8e5..eadd48a6c261 100644 --- a/tools/aapt/AaptAssets.h +++ b/tools/aapt/AaptAssets.h @@ -103,7 +103,7 @@ struct AaptGroupEntry { public: AaptGroupEntry() {} - AaptGroupEntry(const ConfigDescription& config) : mParams(config) {} + explicit AaptGroupEntry(const ConfigDescription& config) : mParams(config) {} bool initFromDirName(const char* dir, String8* resType); @@ -312,7 +312,7 @@ public: : isPublic(false), isJavaSymbol(false), typeCode(TYPE_UNKNOWN) { } - AaptSymbolEntry(const String8& _name) + explicit AaptSymbolEntry(const String8& _name) : name(_name), isPublic(false), isJavaSymbol(false), typeCode(TYPE_UNKNOWN) { } diff --git a/tools/aapt/ApkBuilder.h b/tools/aapt/ApkBuilder.h index 0d7f06b1f323..5d3abc63519f 100644 --- a/tools/aapt/ApkBuilder.h +++ b/tools/aapt/ApkBuilder.h @@ -32,7 +32,7 @@ class AaptFile; class ApkBuilder : public android::RefBase { public: - ApkBuilder(const sp<WeakResourceFilter>& configFilter); + explicit ApkBuilder(const sp<WeakResourceFilter>& configFilter); /** * Tells the builder to generate a separate APK for resources that diff --git a/tools/aapt/CacheUpdater.h b/tools/aapt/CacheUpdater.h index 10a1bbc2f4aa..6fa96d67e6a3 100644 --- a/tools/aapt/CacheUpdater.h +++ b/tools/aapt/CacheUpdater.h @@ -51,7 +51,7 @@ private: class SystemCacheUpdater : public CacheUpdater { public: // Constructor to set bundle to pass to preProcessImage - SystemCacheUpdater (Bundle* b) + explicit SystemCacheUpdater (Bundle* b) : bundle(b) { }; // Make sure all the directories along this path exist diff --git a/tools/aapt/Command.cpp b/tools/aapt/Command.cpp index cbad4b9b48a9..d80aaba8f64b 100644 --- a/tools/aapt/Command.cpp +++ b/tools/aapt/Command.cpp @@ -248,7 +248,7 @@ bail: } static void printResolvedResourceAttribute(const ResTable& resTable, const ResXMLTree& tree, - uint32_t attrRes, String8 attrLabel, String8* outError) + uint32_t attrRes, const String8& attrLabel, String8* outError) { Res_value value; AaptXml::getResolvedResourceAttribute(resTable, tree, attrRes, &value, outError); @@ -399,7 +399,7 @@ static void printUsesImpliedPermission(const String8& name, const String8& reaso ResTable::normalizeForOutput(reason.string()).string()); } -Vector<String8> getNfcAidCategories(AssetManager& assets, String8 xmlPath, bool offHost, +Vector<String8> getNfcAidCategories(AssetManager& assets, const String8& xmlPath, bool offHost, String8 *outError = NULL) { Asset* aidAsset = assets.openNonAsset(xmlPath, Asset::ACCESS_BUFFER); diff --git a/tools/aapt/ConfigDescription.h b/tools/aapt/ConfigDescription.h index 4f999a2ff0c6..09430f2532fa 100644 --- a/tools/aapt/ConfigDescription.h +++ b/tools/aapt/ConfigDescription.h @@ -29,7 +29,7 @@ struct ConfigDescription : public android::ResTable_config { size = sizeof(android::ResTable_config); } - ConfigDescription(const android::ResTable_config&o) { + ConfigDescription(const android::ResTable_config&o) { // NOLINT(implicit) *static_cast<android::ResTable_config*>(this) = o; size = sizeof(android::ResTable_config); } diff --git a/tools/aapt/CrunchCache.cpp b/tools/aapt/CrunchCache.cpp index 0d574cf127dd..7b8a576b88d3 100644 --- a/tools/aapt/CrunchCache.cpp +++ b/tools/aapt/CrunchCache.cpp @@ -94,7 +94,7 @@ void CrunchCache::loadFiles() delete dw; } -bool CrunchCache::needsUpdating(String8 relativePath) const +bool CrunchCache::needsUpdating(const String8& relativePath) const { // Retrieve modification dates for this file entry under the source and // cache directory trees. The vectors will return a modification date of 0 diff --git a/tools/aapt/CrunchCache.h b/tools/aapt/CrunchCache.h index be3da5c40b25..4d6a16922f25 100644 --- a/tools/aapt/CrunchCache.h +++ b/tools/aapt/CrunchCache.h @@ -81,7 +81,7 @@ private: * // Recrunch sourceFile out to destFile. * */ - bool needsUpdating(String8 relativePath) const; + bool needsUpdating(const String8& relativePath) const; // DATA MEMBERS ==================================================== diff --git a/tools/aapt/FileFinder.cpp b/tools/aapt/FileFinder.cpp index 18775c06863f..c9d0744a4463 100644 --- a/tools/aapt/FileFinder.cpp +++ b/tools/aapt/FileFinder.cpp @@ -77,7 +77,7 @@ bool SystemFileFinder::findFiles(String8 basePath, Vector<String8>& extensions, return true; } -void SystemFileFinder::checkAndAddFile(String8 path, const struct stat* stats, +void SystemFileFinder::checkAndAddFile(const String8& path, const struct stat* stats, Vector<String8>& extensions, KeyedVector<String8,time_t>& fileStore) { diff --git a/tools/aapt/FileFinder.h b/tools/aapt/FileFinder.h index 6974aee033a8..f405381ee275 100644 --- a/tools/aapt/FileFinder.h +++ b/tools/aapt/FileFinder.h @@ -72,7 +72,7 @@ private: * time as the value. * */ - static void checkAndAddFile(String8 path, const struct stat* stats, + static void checkAndAddFile(const String8& path, const struct stat* stats, Vector<String8>& extensions, KeyedVector<String8,time_t>& fileStore); diff --git a/tools/aapt/IndentPrinter.h b/tools/aapt/IndentPrinter.h index 6fc94bc927b8..bd0edcbed8ad 100644 --- a/tools/aapt/IndentPrinter.h +++ b/tools/aapt/IndentPrinter.h @@ -3,7 +3,7 @@ class IndentPrinter { public: - IndentPrinter(FILE* stream, int indentSize=2) + explicit IndentPrinter(FILE* stream, int indentSize=2) : mStream(stream) , mIndentSize(indentSize) , mIndent(0) diff --git a/tools/aapt/Resource.cpp b/tools/aapt/Resource.cpp index b278831ddf4e..b4c4d05a7397 100644 --- a/tools/aapt/Resource.cpp +++ b/tools/aapt/Resource.cpp @@ -399,7 +399,7 @@ static void collect_files(const sp<AaptDir>& dir, const DefaultKeyedVector<String8, sp<AaptGroup> >& groups = dir->getFiles(); int N = groups.size(); for (int i=0; i<N; i++) { - String8 leafName = groups.keyAt(i); + const String8& leafName = groups.keyAt(i); const sp<AaptGroup>& group = groups.valueAt(i); const DefaultKeyedVector<AaptGroupEntry, sp<AaptFile> >& files @@ -422,7 +422,7 @@ static void collect_files(const sp<AaptDir>& dir, set->add(leafName, group); resources->add(resType, set); } else { - sp<ResourceTypeSet> set = resources->valueAt(index); + const sp<ResourceTypeSet>& set = resources->valueAt(index); index = set->indexOfKey(leafName); if (index < 0) { if (kIsDebug) { @@ -457,7 +457,7 @@ static void collect_files(const sp<AaptAssets>& ass, int N = dirs.size(); for (int i=0; i<N; i++) { - sp<AaptDir> d = dirs.itemAt(i); + const sp<AaptDir>& d = dirs.itemAt(i); if (kIsDebug) { printf("Collecting dir #%d %p: %s, leaf %s\n", i, d.get(), d->getPath().string(), d->getLeaf().string()); @@ -615,7 +615,7 @@ static bool applyFileOverlay(Bundle *bundle, // get the overlay resources of the requested type ssize_t index = overlayRes->indexOfKey(resTypeString); if (index >= 0) { - sp<ResourceTypeSet> overlaySet = overlayRes->valueAt(index); + const sp<ResourceTypeSet>& overlaySet = overlayRes->valueAt(index); // for each of the resources, check for a match in the previously built // non-overlay "baseset". @@ -765,7 +765,7 @@ bool addTagAttribute(const sp<XMLNode>& node, const char* ns8, return addTagAttribute(node, ns8, attr8, value, errorOnFailedInsert, false); } -static void fullyQualifyClassName(const String8& package, sp<XMLNode> node, +static void fullyQualifyClassName(const String8& package, const sp<XMLNode>& node, const String16& attrName) { XMLNode::attribute_entry* attr = node->editAttribute( String16("http://schemas.android.com/apk/res/android"), attrName); @@ -1350,7 +1350,7 @@ status_t buildResources(Bundle* bundle, const sp<AaptAssets>& assets, sp<ApkBuil ResourceDirIterator it(resources->valueAt(index), String8("values")); ssize_t res; while ((res=it.next()) == NO_ERROR) { - sp<AaptFile> file = it.getFile(); + const sp<AaptFile>& file = it.getFile(); res = compileResourceFile(bundle, assets, file, it.getParams(), (current!=assets), &table); if (res != NO_ERROR) { @@ -2688,7 +2688,7 @@ status_t writeResourceSymbols(Bundle* bundle, const sp<AaptAssets>& assets, String8 dest(bundle->getRClassDir()); if (bundle->getMakePackageDirs()) { - String8 pkg(package); + const String8& pkg(package); const char* last = pkg.string(); const char* s = last-1; do { diff --git a/tools/aapt/ResourceFilter.h b/tools/aapt/ResourceFilter.h index d6430c0409cc..40d5b752000c 100644 --- a/tools/aapt/ResourceFilter.h +++ b/tools/aapt/ResourceFilter.h @@ -78,7 +78,7 @@ private: class StrongResourceFilter : public ResourceFilter { public: StrongResourceFilter() {} - StrongResourceFilter(const std::set<ConfigDescription>& configs) + explicit StrongResourceFilter(const std::set<ConfigDescription>& configs) : mConfigs(configs) {} android::status_t parse(const android::String8& str); @@ -106,7 +106,7 @@ private: */ class InverseResourceFilter : public ResourceFilter { public: - InverseResourceFilter(const android::sp<ResourceFilter>& filter) + explicit InverseResourceFilter(const android::sp<ResourceFilter>& filter) : mFilter(filter) {} bool match(const android::ResTable_config& config) const { diff --git a/tools/aapt/ResourceTable.cpp b/tools/aapt/ResourceTable.cpp index 4d5bb312aaf1..76c59dd57068 100644 --- a/tools/aapt/ResourceTable.cpp +++ b/tools/aapt/ResourceTable.cpp @@ -4081,7 +4081,7 @@ status_t ResourceTable::Type::applyPublicEntryOrder() j = 0; for (i=0; i<N; i++) { - sp<ConfigList> e = origOrder.itemAt(i); + const sp<ConfigList>& e = origOrder.itemAt(i); // There will always be enough room for the remaining entries. while (mOrderedConfigs.itemAt(j) != NULL) { j++; @@ -4203,7 +4203,7 @@ status_t ResourceTable::Package::applyPublicTypeOrder() size_t j=0; for (i=0; i<N; i++) { - sp<Type> t = origOrder.itemAt(i); + const sp<Type>& t = origOrder.itemAt(i); // There will always be enough room for the remaining types. while (mOrderedTypes.itemAt(j) != NULL) { j++; @@ -4636,7 +4636,7 @@ status_t ResourceTable::modifyForCompat(const Bundle* bundle) { c->getEntries(); const size_t entryCount = entries.size(); for (size_t ei = 0; ei < entryCount; ei++) { - sp<Entry> e = entries.valueAt(ei); + const sp<Entry>& e = entries.valueAt(ei); if (e == NULL || e->getType() != Entry::TYPE_BAG) { continue; } diff --git a/tools/aapt/StringPool.h b/tools/aapt/StringPool.h index 4b0d920c3274..625b0bfb3832 100644 --- a/tools/aapt/StringPool.h +++ b/tools/aapt/StringPool.h @@ -41,7 +41,7 @@ class StringPool public: struct entry { entry() : offset(0) { } - entry(const String16& _value) : value(_value), offset(0), hasStyles(false) { } + explicit entry(const String16& _value) : value(_value), offset(0), hasStyles(false) { } entry(const entry& o) : value(o.value), offset(o.offset), hasStyles(o.hasStyles), indices(o.indices), configTypeName(o.configTypeName), configs(o.configs) { } diff --git a/tools/aapt/WorkQueue.h b/tools/aapt/WorkQueue.h index d38f05d034e9..ab5f9691c21d 100644 --- a/tools/aapt/WorkQueue.h +++ b/tools/aapt/WorkQueue.h @@ -47,7 +47,7 @@ public: }; /* Creates a work queue with the specified maximum number of work threads. */ - WorkQueue(size_t maxThreads, bool canCallJava = true); + explicit WorkQueue(size_t maxThreads, bool canCallJava = true); /* Destroys the work queue. * Cancels pending work and waits for all remaining threads to complete. diff --git a/tools/aapt/XMLNode.cpp b/tools/aapt/XMLNode.cpp index 5b215daeb494..15ec4afa52dd 100644 --- a/tools/aapt/XMLNode.cpp +++ b/tools/aapt/XMLNode.cpp @@ -67,7 +67,7 @@ static const String16 RESOURCES_PREFIX_AUTO_PACKAGE(RESOURCES_AUTO_PACKAGE_NAMES static const String16 RESOURCES_PRV_PREFIX(RESOURCES_ROOT_PRV_NAMESPACE); static const String16 RESOURCES_TOOLS_NAMESPACE("http://schemas.android.com/tools"); -String16 getNamespaceResourcePackage(String16 appPackage, String16 namespaceUri, bool* outIsPublic) +String16 getNamespaceResourcePackage(const String16& appPackage, const String16& namespaceUri, bool* outIsPublic) { //printf("%s starts with %s?\n", String8(namespaceUri).string(), // String8(RESOURCES_PREFIX).string()); @@ -98,7 +98,7 @@ String16 getNamespaceResourcePackage(String16 appPackage, String16 namespaceUri, status_t hasSubstitutionErrors(const char* fileName, ResXMLTree* inXml, - String16 str16) + const String16& str16) { const char16_t* str = str16.string(); const char16_t* p = str; diff --git a/tools/aapt/XMLNode.h b/tools/aapt/XMLNode.h index 749bf9f59bf7..ac920186fe63 100644 --- a/tools/aapt/XMLNode.h +++ b/tools/aapt/XMLNode.h @@ -178,7 +178,7 @@ private: XMLNode(const String8& filename, const String16& s1, const String16& s2, bool isNamespace); // Creating a CDATA node. - XMLNode(const String8& filename); + explicit XMLNode(const String8& filename); status_t collect_strings(StringPool* dest, Vector<uint32_t>* outResIds, bool stripComments, bool stripRawValues) const; diff --git a/tools/aapt/pseudolocalize.h b/tools/aapt/pseudolocalize.h index 1faecd14172d..9bb1fd8312b0 100644 --- a/tools/aapt/pseudolocalize.h +++ b/tools/aapt/pseudolocalize.h @@ -43,7 +43,7 @@ class PseudoMethodAccent : public PseudoMethodImpl { class Pseudolocalizer { public: - Pseudolocalizer(PseudolocalizationMethod m); + explicit Pseudolocalizer(PseudolocalizationMethod m); ~Pseudolocalizer() { if (mImpl) delete mImpl; } void setMethod(PseudolocalizationMethod m); String16 start() { return mImpl->start(); } diff --git a/tools/aapt2/ConfigDescription.h b/tools/aapt2/ConfigDescription.h index ef0d147d9d98..6858c624fc80 100644 --- a/tools/aapt2/ConfigDescription.h +++ b/tools/aapt2/ConfigDescription.h @@ -51,7 +51,7 @@ struct ConfigDescription : public android::ResTable_config { static void applyVersionForCompatibility(ConfigDescription* config); ConfigDescription(); - ConfigDescription(const android::ResTable_config& o); + ConfigDescription(const android::ResTable_config& o); // NOLINT(implicit) ConfigDescription(const ConfigDescription& o); ConfigDescription(ConfigDescription&& o); diff --git a/tools/aapt2/Resource.h b/tools/aapt2/Resource.h index 0ba034520563..09a04e0f2afb 100644 --- a/tools/aapt2/Resource.h +++ b/tools/aapt2/Resource.h @@ -100,7 +100,7 @@ struct ResourceNameRef { ResourceNameRef() = default; ResourceNameRef(const ResourceNameRef&) = default; ResourceNameRef(ResourceNameRef&&) = default; - ResourceNameRef(const ResourceName& rhs); + ResourceNameRef(const ResourceName& rhs); // NOLINT(implicit) ResourceNameRef(const StringPiece& p, ResourceType t, const StringPiece& e); ResourceNameRef& operator=(const ResourceNameRef& rhs) = default; ResourceNameRef& operator=(ResourceNameRef&& rhs) = default; @@ -126,7 +126,7 @@ struct ResourceId { ResourceId(); ResourceId(const ResourceId& rhs); - ResourceId(uint32_t resId); + ResourceId(uint32_t resId); // NOLINT(implicit) ResourceId(uint8_t p, uint8_t t, uint16_t e); bool isValid() const; diff --git a/tools/aapt2/ResourceTable.cpp b/tools/aapt2/ResourceTable.cpp index 4d418d9c2e93..460de0e800d3 100644 --- a/tools/aapt2/ResourceTable.cpp +++ b/tools/aapt2/ResourceTable.cpp @@ -274,7 +274,7 @@ bool ResourceTable::addResource(const ResourceNameRef& name, } bool ResourceTable::addResource(const ResourceNameRef& name, - const ResourceId resId, + const ResourceId& resId, const ConfigDescription& config, const StringPiece& product, std::unique_ptr<Value> value, @@ -325,7 +325,7 @@ bool ResourceTable::addResourceAllowMangled(const ResourceNameRef& name, } bool ResourceTable::addResourceAllowMangled(const ResourceNameRef& name, - const ResourceId id, + const ResourceId& id, const ConfigDescription& config, const StringPiece& product, std::unique_ptr<Value> value, @@ -335,12 +335,12 @@ bool ResourceTable::addResourceAllowMangled(const ResourceNameRef& name, } bool ResourceTable::addResourceImpl(const ResourceNameRef& name, - const ResourceId resId, + const ResourceId& resId, const ConfigDescription& config, const StringPiece& product, std::unique_ptr<Value> value, const char* validChars, - std::function<int(Value*,Value*)> conflictResolver, + const std::function<int(Value*,Value*)>& conflictResolver, IDiagnostics* diag) { assert(value && "value can't be nullptr"); assert(diag && "diagnostics can't be nullptr"); @@ -426,18 +426,18 @@ bool ResourceTable::addResourceImpl(const ResourceNameRef& name, return true; } -bool ResourceTable::setSymbolState(const ResourceNameRef& name, const ResourceId resId, +bool ResourceTable::setSymbolState(const ResourceNameRef& name, const ResourceId& resId, const Symbol& symbol, IDiagnostics* diag) { return setSymbolStateImpl(name, resId, symbol, kValidNameChars, diag); } bool ResourceTable::setSymbolStateAllowMangled(const ResourceNameRef& name, - const ResourceId resId, + const ResourceId& resId, const Symbol& symbol, IDiagnostics* diag) { return setSymbolStateImpl(name, resId, symbol, kValidNameMangledChars, diag); } -bool ResourceTable::setSymbolStateImpl(const ResourceNameRef& name, const ResourceId resId, +bool ResourceTable::setSymbolStateImpl(const ResourceNameRef& name, const ResourceId& resId, const Symbol& symbol, const char* validChars, IDiagnostics* diag) { assert(diag && "diagnostics can't be nullptr"); diff --git a/tools/aapt2/ResourceTable.h b/tools/aapt2/ResourceTable.h index a5efe355a76c..6b52a4360b7a 100644 --- a/tools/aapt2/ResourceTable.h +++ b/tools/aapt2/ResourceTable.h @@ -103,7 +103,7 @@ public: */ std::vector<std::unique_ptr<ResourceConfigValue>> values; - ResourceEntry(const StringPiece& name) : name(name.toString()) { } + explicit ResourceEntry(const StringPiece& name) : name(name.toString()) { } ResourceConfigValue* findValue(const ConfigDescription& config); ResourceConfigValue* findValue(const ConfigDescription& config, const StringPiece& product); @@ -200,7 +200,7 @@ public: IDiagnostics* diag); bool addResource(const ResourceNameRef& name, - const ResourceId resId, + const ResourceId& resId, const ConfigDescription& config, const StringPiece& product, std::unique_ptr<Value> value, @@ -231,19 +231,19 @@ public: IDiagnostics* diag); bool addResourceAllowMangled(const ResourceNameRef& name, - const ResourceId id, + const ResourceId& id, const ConfigDescription& config, const StringPiece& product, std::unique_ptr<Value> value, IDiagnostics* diag); bool setSymbolState(const ResourceNameRef& name, - const ResourceId resId, + const ResourceId& resId, const Symbol& symbol, IDiagnostics* diag); bool setSymbolStateAllowMangled(const ResourceNameRef& name, - const ResourceId resId, + const ResourceId& resId, const Symbol& symbol, IDiagnostics* diag); @@ -294,16 +294,16 @@ private: IDiagnostics* diag); bool addResourceImpl(const ResourceNameRef& name, - ResourceId resId, + const ResourceId& resId, const ConfigDescription& config, const StringPiece& product, std::unique_ptr<Value> value, const char* validChars, - std::function<int(Value*,Value*)> conflictResolver, + const std::function<int(Value*,Value*)>& conflictResolver, IDiagnostics* diag); bool setSymbolStateImpl(const ResourceNameRef& name, - ResourceId resId, + const ResourceId& resId, const Symbol& symbol, const char* validChars, IDiagnostics* diag); diff --git a/tools/aapt2/ResourceUtils.cpp b/tools/aapt2/ResourceUtils.cpp index 7dc88dedc96e..773616d6aa71 100644 --- a/tools/aapt2/ResourceUtils.cpp +++ b/tools/aapt2/ResourceUtils.cpp @@ -545,7 +545,7 @@ uint32_t androidTypeToAttributeTypeMask(uint16_t type) { std::unique_ptr<Item> parseItemForAttribute( const StringPiece& value, uint32_t typeMask, - std::function<void(const ResourceName&)> onCreateReference) { + const std::function<void(const ResourceName&)>& onCreateReference) { std::unique_ptr<BinaryPrimitive> nullOrEmpty = tryParseNullOrEmpty(value); if (nullOrEmpty) { return std::move(nullOrEmpty); @@ -604,7 +604,7 @@ std::unique_ptr<Item> parseItemForAttribute( */ std::unique_ptr<Item> parseItemForAttribute( const StringPiece& str, const Attribute* attr, - std::function<void(const ResourceName&)> onCreateReference) { + const std::function<void(const ResourceName&)>& onCreateReference) { const uint32_t typeMask = attr->typeMask; std::unique_ptr<Item> value = parseItemForAttribute(str, typeMask, onCreateReference); if (value) { diff --git a/tools/aapt2/ResourceUtils.h b/tools/aapt2/ResourceUtils.h index 31b8e89850e5..a57d89dd0233 100644 --- a/tools/aapt2/ResourceUtils.h +++ b/tools/aapt2/ResourceUtils.h @@ -163,11 +163,11 @@ std::unique_ptr<BinaryPrimitive> tryParseFlagSymbol(const Attribute* enumAttr, */ std::unique_ptr<Item> parseItemForAttribute( const StringPiece& value, const Attribute* attr, - std::function<void(const ResourceName&)> onCreateReference = {}); + const std::function<void(const ResourceName&)>& onCreateReference = {}); std::unique_ptr<Item> parseItemForAttribute( const StringPiece& value, uint32_t typeMask, - std::function<void(const ResourceName&)> onCreateReference = {}); + const std::function<void(const ResourceName&)>& onCreateReference = {}); uint32_t androidTypeToAttributeTypeMask(uint16_t type); diff --git a/tools/aapt2/ResourceValues.h b/tools/aapt2/ResourceValues.h index 8ae71ad82a60..e6af7166c08f 100644 --- a/tools/aapt2/ResourceValues.h +++ b/tools/aapt2/ResourceValues.h @@ -198,7 +198,7 @@ struct Id : public BaseItem<Id> { struct RawString : public BaseItem<RawString> { StringPool::Ref value; - RawString(const StringPool::Ref& ref); + explicit RawString(const StringPool::Ref& ref); bool equals(const Value* value) const override; bool flatten(android::Res_value* outValue) const override; @@ -209,7 +209,7 @@ struct RawString : public BaseItem<RawString> { struct String : public BaseItem<String> { StringPool::Ref value; - String(const StringPool::Ref& ref); + explicit String(const StringPool::Ref& ref); bool equals(const Value* value) const override; bool flatten(android::Res_value* outValue) const override; @@ -220,7 +220,7 @@ struct String : public BaseItem<String> { struct StyledString : public BaseItem<StyledString> { StringPool::StyleRef value; - StyledString(const StringPool::StyleRef& ref); + explicit StyledString(const StringPool::StyleRef& ref); bool equals(const Value* value) const override; bool flatten(android::Res_value* outValue) const override; @@ -237,7 +237,7 @@ struct FileReference : public BaseItem<FileReference> { io::IFile* file = nullptr; FileReference() = default; - FileReference(const StringPool::Ref& path); + explicit FileReference(const StringPool::Ref& path); bool equals(const Value* value) const override; bool flatten(android::Res_value* outValue) const override; @@ -252,7 +252,7 @@ struct BinaryPrimitive : public BaseItem<BinaryPrimitive> { android::Res_value value; BinaryPrimitive() = default; - BinaryPrimitive(const android::Res_value& val); + explicit BinaryPrimitive(const android::Res_value& val); BinaryPrimitive(uint8_t dataType, uint32_t data); bool equals(const Value* value) const override; @@ -272,7 +272,7 @@ struct Attribute : public BaseValue<Attribute> { int32_t maxInt; std::vector<Symbol> symbols; - Attribute(bool w, uint32_t t = 0u); + explicit Attribute(bool w, uint32_t t = 0u); bool equals(const Value* value) const override; Attribute* clone(StringPool* newPool) const override; diff --git a/tools/aapt2/SdkConstants.cpp b/tools/aapt2/SdkConstants.cpp index 91e755de2514..ccf0383bd374 100644 --- a/tools/aapt2/SdkConstants.cpp +++ b/tools/aapt2/SdkConstants.cpp @@ -52,7 +52,7 @@ static bool lessEntryId(const std::pair<uint16_t, size_t>& p, uint16_t entryId) return p.first < entryId; } -size_t findAttributeSdkLevel(ResourceId id) { +size_t findAttributeSdkLevel(const ResourceId& id) { if (id.packageId() != 0x01 && id.typeId() != 0x01) { return 0; } diff --git a/tools/aapt2/SdkConstants.h b/tools/aapt2/SdkConstants.h index f28679fde0de..c9dbdca29513 100644 --- a/tools/aapt2/SdkConstants.h +++ b/tools/aapt2/SdkConstants.h @@ -47,7 +47,7 @@ enum { SDK_MARSHMALLOW = 23, }; -size_t findAttributeSdkLevel(ResourceId id); +size_t findAttributeSdkLevel(const ResourceId& id); size_t findAttributeSdkLevel(const ResourceName& name); std::pair<StringPiece, int> getDevelopmentSdkCodeNameAndVersion(); diff --git a/tools/aapt2/StringPool.h b/tools/aapt2/StringPool.h index 72ae9d184a78..13545bef53ab 100644 --- a/tools/aapt2/StringPool.h +++ b/tools/aapt2/StringPool.h @@ -65,7 +65,7 @@ public: private: friend class StringPool; - Ref(Entry* entry); + explicit Ref(Entry* entry); Entry* mEntry; }; @@ -88,7 +88,7 @@ public: private: friend class StringPool; - StyleRef(StyleEntry* entry); + explicit StyleRef(StyleEntry* entry); StyleEntry* mEntry; }; diff --git a/tools/aapt2/compile/IdAssigner.cpp b/tools/aapt2/compile/IdAssigner.cpp index 501ae9d08c08..4a3f1e10b6db 100644 --- a/tools/aapt2/compile/IdAssigner.cpp +++ b/tools/aapt2/compile/IdAssigner.cpp @@ -28,7 +28,7 @@ namespace aapt { * Assigns the intended ID to the ResourceTablePackage, ResourceTableType, and ResourceEntry, * as long as there is no existing ID or the ID is the same. */ -static bool assignId(IDiagnostics* diag, const ResourceId id, const ResourceName& name, +static bool assignId(IDiagnostics* diag, const ResourceId& id, const ResourceName& name, ResourceTablePackage* pkg, ResourceTableType* type, ResourceEntry* entry) { if (pkg->id.value() == id.packageId()) { if (!type->id || type->id.value() == id.typeId()) { diff --git a/tools/aapt2/flatten/TableFlattener_test.cpp b/tools/aapt2/flatten/TableFlattener_test.cpp index 0b92ba5b229d..b25bfa73dd39 100644 --- a/tools/aapt2/flatten/TableFlattener_test.cpp +++ b/tools/aapt2/flatten/TableFlattener_test.cpp @@ -64,7 +64,7 @@ public: ::testing::AssertionResult exists(ResTable* table, const StringPiece& expectedName, - const ResourceId expectedId, + const ResourceId& expectedId, const ConfigDescription& expectedConfig, const uint8_t expectedDataType, const uint32_t expectedData, const uint32_t expectedSpecFlags) { diff --git a/tools/aapt2/flatten/XmlFlattener_test.cpp b/tools/aapt2/flatten/XmlFlattener_test.cpp index d26f2e4ab7ea..4d1e178c4436 100644 --- a/tools/aapt2/flatten/XmlFlattener_test.cpp +++ b/tools/aapt2/flatten/XmlFlattener_test.cpp @@ -43,7 +43,7 @@ public: } ::testing::AssertionResult flatten(xml::XmlResource* doc, android::ResXMLTree* outTree, - XmlFlattenerOptions options = {}) { + const XmlFlattenerOptions& options = {}) { using namespace android; // For NO_ERROR on windows because it is a macro. BigBuffer buffer(1024); diff --git a/tools/aapt2/integration-tests/AppOne/AndroidManifest.xml b/tools/aapt2/integration-tests/AppOne/AndroidManifest.xml index b6d8f2d1b748..1156b01fe70d 100644 --- a/tools/aapt2/integration-tests/AppOne/AndroidManifest.xml +++ b/tools/aapt2/integration-tests/AppOne/AndroidManifest.xml @@ -14,4 +14,7 @@ limitations under the License. --> -<manifest package="com.android.aapt.app.one" /> +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.android.aapt.app.one" coreApp="true"> + <uses-sdk android:minSdkVersion="21" /> +</manifest> diff --git a/tools/aapt2/link/Link.cpp b/tools/aapt2/link/Link.cpp index 45472fff5088..ff777a3b60eb 100644 --- a/tools/aapt2/link/Link.cpp +++ b/tools/aapt2/link/Link.cpp @@ -528,7 +528,7 @@ bool ResourceFileFlattener::flatten(ResourceTable* table, IArchiveWriter* archiv static bool writeStableIdMapToPath(IDiagnostics* diag, const std::unordered_map<ResourceName, ResourceId>& idMap, - const std::string idMapPath) { + const std::string& idMapPath) { std::ofstream fout(idMapPath, std::ofstream::binary); if (!fout) { diag->error(DiagMessage(idMapPath) << strerror(errno)); @@ -823,7 +823,7 @@ public: } bool writeJavaFile(ResourceTable* table, const StringPiece& packageNameToGenerate, - const StringPiece& outPackage, JavaClassGeneratorOptions javaOptions) { + const StringPiece& outPackage, const JavaClassGeneratorOptions& javaOptions) { if (!mOptions.generateJavaClassPath) { return true; } @@ -1191,6 +1191,12 @@ public: mContext->getDiagnostics())) { AppInfo& appInfo = maybeAppInfo.value(); mContext->setCompilationPackage(appInfo.package); + if (appInfo.minSdkVersion) { + if (Maybe<int> maybeMinSdkVersion = + ResourceUtils::tryParseSdkVersion(appInfo.minSdkVersion.value())) { + mContext->setMinSdkVersion(maybeMinSdkVersion.value()); + } + } } else { return 1; } @@ -1393,32 +1399,6 @@ public: return 1; } - // Must come before ResourceFileFlattener as ResourceFileFlattener - // relies on the minSdkVersion to properly flatten files. - Maybe<AppInfo> maybeAppInfo = extractAppInfoFromManifest(manifestXml.get(), - mContext->getDiagnostics()); - if (maybeAppInfo && maybeAppInfo.value().minSdkVersion) { - if (Maybe<int> maybeMinSdkVersion = - ResourceUtils::tryParseSdkVersion(maybeAppInfo.value().minSdkVersion.value())) { - mContext->setMinSdkVersion(maybeMinSdkVersion.value()); - } - } - - ResourceFileFlattenerOptions fileFlattenerOptions; - fileFlattenerOptions.keepRawValues = mOptions.staticLib; - fileFlattenerOptions.doNotCompressAnything = mOptions.doNotCompressAnything; - fileFlattenerOptions.extensionsToNotCompress = mOptions.extensionsToNotCompress; - fileFlattenerOptions.noAutoVersion = mOptions.noAutoVersion; - fileFlattenerOptions.noVersionVectors = mOptions.noVersionVectors; - fileFlattenerOptions.updateProguardSpec = - static_cast<bool>(mOptions.generateProguardRulesPath); - ResourceFileFlattener fileFlattener(fileFlattenerOptions, mContext, &proguardKeepSet); - - if (!fileFlattener.flatten(&mFinalTable, archiveWriter.get())) { - mContext->getDiagnostics()->error(DiagMessage() << "failed linking file resources"); - return 1; - } - if (!mOptions.noAutoVersion) { AutoVersioner versioner; if (!versioner.consume(mContext, &mFinalTable)) { @@ -1440,6 +1420,23 @@ public: } } + // Write out the table to an archive. Optimizations to the table should come before this + // step. + ResourceFileFlattenerOptions fileFlattenerOptions; + fileFlattenerOptions.keepRawValues = mOptions.staticLib; + fileFlattenerOptions.doNotCompressAnything = mOptions.doNotCompressAnything; + fileFlattenerOptions.extensionsToNotCompress = mOptions.extensionsToNotCompress; + fileFlattenerOptions.noAutoVersion = mOptions.noAutoVersion; + fileFlattenerOptions.noVersionVectors = mOptions.noVersionVectors; + fileFlattenerOptions.updateProguardSpec = + static_cast<bool>(mOptions.generateProguardRulesPath); + ResourceFileFlattener fileFlattener(fileFlattenerOptions, mContext, &proguardKeepSet); + + if (!fileFlattener.flatten(&mFinalTable, archiveWriter.get())) { + mContext->getDiagnostics()->error(DiagMessage() << "failed linking file resources"); + return 1; + } + if (mOptions.staticLib) { if (!flattenTableToPb(&mFinalTable, archiveWriter.get())) { mContext->getDiagnostics()->error(DiagMessage() diff --git a/tools/aapt2/link/ManifestFixer.cpp b/tools/aapt2/link/ManifestFixer.cpp index 1203db7734ea..e7edcc5d5498 100644 --- a/tools/aapt2/link/ManifestFixer.cpp +++ b/tools/aapt2/link/ManifestFixer.cpp @@ -81,6 +81,22 @@ static bool verifyManifest(xml::Element* el, SourcePathDiagnostics* diag) { return true; } +/** + * The coreApp attribute in <manifest> is not a regular AAPT attribute, so type checking on it + * is manual. + */ +static bool fixCoreAppAttribute(xml::Element* el, SourcePathDiagnostics* diag) { + if (xml::Attribute* attr = el->findAttribute("", "coreApp")) { + std::unique_ptr<BinaryPrimitive> result = ResourceUtils::tryParseBool(attr->value); + if (!result) { + diag->error(DiagMessage(el->lineNumber) << "attribute coreApp must be a boolean"); + return false; + } + attr->compiledValue = std::move(result); + } + return true; +} + bool ManifestFixer::buildRules(xml::XmlActionExecutor* executor, IDiagnostics* diag) { // First verify some options. if (mOptions.renameManifestPackage) { @@ -111,6 +127,7 @@ bool ManifestFixer::buildRules(xml::XmlActionExecutor* executor, IDiagnostics* d // Manifest actions. xml::XmlNodeAction& manifestAction = (*executor)["manifest"]; manifestAction.action(verifyManifest); + manifestAction.action(fixCoreAppAttribute); manifestAction.action([&](xml::Element* el) -> bool { if (mOptions.versionNameDefault) { if (el->findAttribute(xml::kSchemaAndroid, "versionName") == nullptr) { diff --git a/tools/aapt2/link/ManifestFixer_test.cpp b/tools/aapt2/link/ManifestFixer_test.cpp index 1c69a8ce738b..16ab9ab15b63 100644 --- a/tools/aapt2/link/ManifestFixer_test.cpp +++ b/tools/aapt2/link/ManifestFixer_test.cpp @@ -253,4 +253,24 @@ TEST_F(ManifestFixerTest, UseDefaultVersionNameAndCode) { EXPECT_EQ(std::string("0x10000000"), attr->value); } +TEST_F(ManifestFixerTest, EnsureManifestAttributesAreTyped) { + EXPECT_EQ(nullptr, verify("<manifest package=\"android\" coreApp=\"hello\" />")); + EXPECT_EQ(nullptr, verify("<manifest package=\"android\" coreApp=\"1dp\" />")); + + std::unique_ptr<xml::XmlResource> doc = + verify("<manifest package=\"android\" coreApp=\"true\" />"); + ASSERT_NE(nullptr, doc); + + xml::Element* el = xml::findRootElement(doc.get()); + ASSERT_NE(nullptr, el); + + EXPECT_EQ("manifest", el->name); + + xml::Attribute* attr = el->findAttribute("", "coreApp"); + ASSERT_NE(nullptr, attr); + + EXPECT_NE(nullptr, attr->compiledValue); + EXPECT_NE(nullptr, valueCast<BinaryPrimitive>(attr->compiledValue.get())); +} + } // namespace aapt diff --git a/tools/aapt2/link/TableMerger.cpp b/tools/aapt2/link/TableMerger.cpp index 2cd2639ec228..379c991c98d2 100644 --- a/tools/aapt2/link/TableMerger.cpp +++ b/tools/aapt2/link/TableMerger.cpp @@ -135,14 +135,14 @@ bool TableMerger::doMerge(const Source& src, const bool manglePackage, const bool overlay, const bool allowNewResources, - FileMergeCallback callback) { + const FileMergeCallback& callback) { bool error = false; for (auto& srcType : srcPackage->types) { ResourceTableType* dstType = mMasterPackage->findOrCreateType(srcType->type); if (srcType->symbolStatus.state == SymbolState::kPublic) { if (dstType->symbolStatus.state == SymbolState::kPublic && dstType->id && srcType->id - && dstType->id.value() == srcType->id.value()) { + && dstType->id.value() != srcType->id.value()) { // Both types are public and have different IDs. mContext->getDiagnostics()->error(DiagMessage(src) << "can not merge type '" diff --git a/tools/aapt2/link/TableMerger.h b/tools/aapt2/link/TableMerger.h index 6997f936add1..3473a27f6142 100644 --- a/tools/aapt2/link/TableMerger.h +++ b/tools/aapt2/link/TableMerger.h @@ -115,7 +115,7 @@ private: const bool manglePackage, const bool overlay, const bool allowNewResources, - FileMergeCallback callback); + const FileMergeCallback& callback); std::unique_ptr<FileReference> cloneAndMangleFile(const std::string& package, const FileReference& value); diff --git a/tools/aapt2/link/TableMerger_test.cpp b/tools/aapt2/link/TableMerger_test.cpp index 300b56ddb3a1..ff3e21f12d19 100644 --- a/tools/aapt2/link/TableMerger_test.cpp +++ b/tools/aapt2/link/TableMerger_test.cpp @@ -164,6 +164,63 @@ TEST_F(TableMergerTest, OverrideResourceWithOverlay) { EXPECT_EQ(0x0u, foo->value.data); } +TEST_F(TableMergerTest, OverrideSameResourceIdsWithOverlay) { + std::unique_ptr<ResourceTable> base = test::ResourceTableBuilder() + .setPackageId("", 0x7f) + .setSymbolState("bool/foo", ResourceId(0x7f, 0x01, 0x0001), SymbolState::kPublic) + .build(); + std::unique_ptr<ResourceTable> overlay = test::ResourceTableBuilder() + .setPackageId("", 0x7f) + .setSymbolState("bool/foo", ResourceId(0x7f, 0x01, 0x0001), SymbolState::kPublic) + .build(); + + ResourceTable finalTable; + TableMergerOptions tableMergerOptions; + tableMergerOptions.autoAddOverlay = false; + TableMerger merger(mContext.get(), &finalTable, tableMergerOptions); + + ASSERT_TRUE(merger.merge({}, base.get())); + ASSERT_TRUE(merger.mergeOverlay({}, overlay.get())); +} + +TEST_F(TableMergerTest, FailToOverrideConflictingTypeIdsWithOverlay) { + std::unique_ptr<ResourceTable> base = test::ResourceTableBuilder() + .setPackageId("", 0x7f) + .setSymbolState("bool/foo", ResourceId(0x7f, 0x01, 0x0001), SymbolState::kPublic) + .build(); + std::unique_ptr<ResourceTable> overlay = test::ResourceTableBuilder() + .setPackageId("", 0x7f) + .setSymbolState("bool/foo", ResourceId(0x7f, 0x02, 0x0001), SymbolState::kPublic) + .build(); + + ResourceTable finalTable; + TableMergerOptions tableMergerOptions; + tableMergerOptions.autoAddOverlay = false; + TableMerger merger(mContext.get(), &finalTable, tableMergerOptions); + + ASSERT_TRUE(merger.merge({}, base.get())); + ASSERT_FALSE(merger.mergeOverlay({}, overlay.get())); +} + +TEST_F(TableMergerTest, FailToOverrideConflictingEntryIdsWithOverlay) { + std::unique_ptr<ResourceTable> base = test::ResourceTableBuilder() + .setPackageId("", 0x7f) + .setSymbolState("bool/foo", ResourceId(0x7f, 0x01, 0x0001), SymbolState::kPublic) + .build(); + std::unique_ptr<ResourceTable> overlay = test::ResourceTableBuilder() + .setPackageId("", 0x7f) + .setSymbolState("bool/foo", ResourceId(0x7f, 0x01, 0x0002), SymbolState::kPublic) + .build(); + + ResourceTable finalTable; + TableMergerOptions tableMergerOptions; + tableMergerOptions.autoAddOverlay = false; + TableMerger merger(mContext.get(), &finalTable, tableMergerOptions); + + ASSERT_TRUE(merger.merge({}, base.get())); + ASSERT_FALSE(merger.mergeOverlay({}, overlay.get())); +} + TEST_F(TableMergerTest, MergeAddResourceFromOverlay) { std::unique_ptr<ResourceTable> tableA = test::ResourceTableBuilder() .setPackageId("", 0x7f) diff --git a/tools/aapt2/link/XmlReferenceLinker.cpp b/tools/aapt2/link/XmlReferenceLinker.cpp index 02af5e3af7ab..a29d8dcfe3c6 100644 --- a/tools/aapt2/link/XmlReferenceLinker.cpp +++ b/tools/aapt2/link/XmlReferenceLinker.cpp @@ -126,8 +126,9 @@ public: mError = true; } - } else { - // We still encode references. + } else if (!attr.compiledValue) { + // We still encode references, but only if we haven't manually set this to + // another compiled value. attr.compiledValue = ResourceUtils::tryParseReference(attr.value); } diff --git a/tools/aapt2/process/SymbolTable.cpp b/tools/aapt2/process/SymbolTable.cpp index 6c506dfe1749..0c927182ecda 100644 --- a/tools/aapt2/process/SymbolTable.cpp +++ b/tools/aapt2/process/SymbolTable.cpp @@ -63,7 +63,7 @@ const SymbolTable::Symbol* SymbolTable::findByName(const ResourceName& name) { return nullptr; } -const SymbolTable::Symbol* SymbolTable::findById(ResourceId id) { +const SymbolTable::Symbol* SymbolTable::findById(const ResourceId& id) { if (const std::shared_ptr<Symbol>& s = mIdCache.get(id)) { return s.get(); } diff --git a/tools/aapt2/process/SymbolTable.h b/tools/aapt2/process/SymbolTable.h index 43f4dd7fb869..bd01b64281d5 100644 --- a/tools/aapt2/process/SymbolTable.h +++ b/tools/aapt2/process/SymbolTable.h @@ -86,7 +86,7 @@ public: * are typically stored in a cache which may evict entries. */ const Symbol* findByName(const ResourceName& name); - const Symbol* findById(ResourceId id); + const Symbol* findById(const ResourceId& id); /** * Let's the ISymbolSource decide whether looking up by name or ID is faster, if both diff --git a/tools/aapt2/proto/TableProtoDeserializer.cpp b/tools/aapt2/proto/TableProtoDeserializer.cpp index 98ff87f7af30..ca25c6a83dd9 100644 --- a/tools/aapt2/proto/TableProtoDeserializer.cpp +++ b/tools/aapt2/proto/TableProtoDeserializer.cpp @@ -228,7 +228,7 @@ private: } } else if (pbValue.has_compound_value()) { - const pb::CompoundValue pbCompoundValue = pbValue.compound_value(); + const pb::CompoundValue& pbCompoundValue = pbValue.compound_value(); if (pbCompoundValue.has_attr()) { const pb::Attribute& pbAttr = pbCompoundValue.attr(); std::unique_ptr<Attribute> attr = util::make_unique<Attribute>(isWeak); diff --git a/wifi/java/android/net/wifi/IWifiManager.aidl b/wifi/java/android/net/wifi/IWifiManager.aidl index 3674f0f4baa7..b62ffac3efa9 100644 --- a/wifi/java/android/net/wifi/IWifiManager.aidl +++ b/wifi/java/android/net/wifi/IWifiManager.aidl @@ -89,7 +89,7 @@ interface IWifiManager WifiInfo getConnectionInfo(); - boolean setWifiEnabled(boolean enable); + boolean setWifiEnabled(String packageName, boolean enable); int getWifiEnabledState(); diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java index 6cf1921524b3..b134cf7a00a4 100644 --- a/wifi/java/android/net/wifi/WifiManager.java +++ b/wifi/java/android/net/wifi/WifiManager.java @@ -19,6 +19,7 @@ package android.net.wifi; import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; import android.annotation.SystemApi; +import android.bluetooth.BluetoothAdapter; import android.content.Context; import android.net.ConnectivityManager; import android.net.DhcpInfo; @@ -561,6 +562,28 @@ public class WifiManager { public static final String ACTION_PICK_WIFI_NETWORK = "android.net.wifi.PICK_WIFI_NETWORK"; /** + * Activity Action: Show UI to get user approval to enable WiFi. + * <p>Input: {@link android.content.Intent#EXTRA_PACKAGE_NAME} string extra with + * the name of the app requesting the action. + * <p>Output: Nothing. + * + * @hide + */ + @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) + public static final String ACTION_REQUEST_ENABLE = "android.net.wifi.action.REQUEST_ENABLE"; + + /** + * Activity Action: Show UI to get user approval to disable WiFi. + * <p>Input: {@link android.content.Intent#EXTRA_PACKAGE_NAME} string extra with + * the name of the app requesting the action. + * <p>Output: Nothing. + * + * @hide + */ + @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) + public static final String ACTION_REQUEST_DISABLE = "android.net.wifi.action.REQUEST_DISABLE"; + + /** * Internally used Wi-Fi lock mode representing the case were no locks are held. * @hide */ @@ -1443,7 +1466,7 @@ public class WifiManager { */ public boolean setWifiEnabled(boolean enabled) { try { - return mService.setWifiEnabled(enabled); + return mService.setWifiEnabled(mContext.getOpPackageName(), enabled); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } |