乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      alarm

       老匹夫 2016-01-16

      關(guān)于時間,我們還知之甚少。

      不知道是誰發(fā)現(xiàn)了時間這個 NB 的概念! 有了時間,使得我們可以知道從一個事件到另外一個事件,中間經(jīng)歷了多久。時間參考系的建立,使得我們可以即使在不同的地點(diǎn)也可以取得同步,完成協(xié)作。

      每個系統(tǒng)都要維持一個時鐘系統(tǒng),一方面維持自身的秩序,另一方面和外界取得一致。

      Linux 和 Android 都不例外。在手機(jī)上我們需要時間系統(tǒng)提供什么樣的服務(wù)呢?

      • 允許我設(shè)置時間/同步時間。
      • 告訴我現(xiàn)在是什么時間。
      • 告訴我系統(tǒng)運(yùn)行了多長時間。
      • 允許我設(shè)置特定時間提醒。

      先來看看設(shè)置特定時間提醒這個功能。

      這個特定時間,有兩個參考系:

      • RTC
      • ELAPSED_REALTIME

      RTC 指得就是當(dāng)前時間,UTC時間,java api System.currentTimeMillis() 返回的時間,通過這個時間我們知道現(xiàn)在是幾年幾月幾日幾時幾分幾秒。

      ELAPSED_REALTIME 指的是過去的時間,從開機(jī)開始過去了多久, java api SystemClock.elapsedRealtime() 返回的時間, 通過這個時間我們知道系統(tǒng)運(yùn)行了多久。

      由于手機(jī)系統(tǒng)會有 “休眠” 狀態(tài),特定時間提醒這個服務(wù)在 “休眠” 狀態(tài)可以有兩種選擇,喚醒手機(jī)提醒,或者不喚醒手機(jī),等待手機(jī)被其他原因喚醒后再提醒。針對這個特性,又添加了兩種類型:

      • RTC_WAKEUP
      • ELAPSED_REALTIME_WAKEUP

      RTC_WAKEUP 基于 UTC 時間,喚醒手機(jī)進(jìn)行提醒,RTC 默認(rèn)不會喚醒手機(jī)。

      ELAPSED_REALTIME_WAKEUP 類似的,基于開機(jī)過去時間,喚醒手機(jī)進(jìn)行提醒。ELAPSED_REALTIME 不會。

      先看下在 app layer 如何設(shè)置特定時間提醒:

      packages/apps/DeskClock/src/com/android/deskclock/alarms/AlarmStateManager.java
      1
      2
      
       AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
       am.set(AlarmManager.RTC_WAKEUP, timeInMillis, pendingIntent);
      

      獲取 AlarmManager ,設(shè)置在 RTC 時間 timeInMillis 喚醒并觸發(fā) pendingIntent 提醒。

      我們知道 AlarmManager 是 AlarmManagerService 的代理,它最后會 IPC到 AlarmManagerService 調(diào)用相關(guān)的接口。

      framework/base/core/java/android/app/AlarmManager.java
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      
       public void setExact(int type, long triggerAtMillis, PendingIntent operation) {
           setImpl(type, triggerAtMillis, WINDOW_EXACT, 0, operation, null);
       }
      
       private void setImpl(int type, long triggerAtMillis, long windowMillis, long intervalMillis,
               PendingIntent operation, WorkSource workSource) {
      ...
        try {
               mService.set(type, triggerAtMillis, windowMillis, intervalMillis, operation,
                       workSource);
           } catch (RemoteException ex) {
           }
      }
      

      到 AlarmManagerService :

      framework/base/core/java/android/app/AlarmManager.java
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      51
      52
      53
      54
      55
      56
      57
      58
      59
      60
      61
      62
      63
      64
      65
      66
      67
      68
      69
      
       @Override
          public void set(int type, long triggerAtTime, long windowLength, long interval,
                  PendingIntent operation, WorkSource workSource) {
              if (workSource != null) {
                  mContext.enforceCallingPermission(
                          android.Manifest.permission.UPDATE_DEVICE_STATS,
                          "AlarmManager.set");
              }
      
              set(type, triggerAtTime, windowLength, interval, operation, false, workSource);
          }
      ->
       public void set(int type, long triggerAtTime, long windowLength, long interval,
                  PendingIntent operation, boolean isStandalone, WorkSource workSource) {
      ...
       setImplLocked(type, triggerAtTime, triggerElapsed, windowLength, maxElapsed,
                          interval, operation, isStandalone, true, workSource);
      }
      
      ->
      
       private void setImplLocked(int type, long when, long whenElapsed, long windowLength,
                  long maxWhen, long interval, PendingIntent operation, boolean isStandalone,
                  boolean doValidate, WorkSource workSource) {
      ...
      rescheduleKernelAlarmsLocked();
      }
      
      ->
      
        private void rescheduleKernelAlarmsLocked() {
              // Schedule the next upcoming wakeup alarm.  If there is a deliverable batch
              // prior to that which contains no wakeups, we schedule that as well.
              if (mAlarmBatches.size() > 0) {
                  final Batch firstWakeup = findFirstWakeupBatchLocked();
                  final Batch firstBatch = mAlarmBatches.get(0);
                  if (firstWakeup != null && mNextWakeup != firstWakeup.start) {
                      mNextWakeup = firstWakeup.start;
                      setLocked(ELAPSED_REALTIME_WAKEUP, firstWakeup.start);
                  }
                  if (firstBatch != firstWakeup && mNextNonWakeup != firstBatch.start) {
                      mNextNonWakeup = firstBatch.start;
                      setLocked(ELAPSED_REALTIME, firstBatch.start);
                  }
              }
          }
      
      ->
      
       private void setLocked(int type, long when)
          {
                if (mDescriptor != -1)
              {
                  // The kernel never triggers alarms with negative wakeup times
                  // so we ensure they are positive.
                  long alarmSeconds, alarmNanoseconds;
                  if (when < 0) {
                      alarmSeconds = 0;
                      alarmNanoseconds = 0;
                  } else {
                      alarmSeconds = when / 1000;
                      alarmNanoseconds = (when % 1000) * 1000 * 1000;
                  }
      
                  set(mDescriptor, type, alarmSeconds, alarmNanoseconds);
          }
      
      ->
      private native void set(int fd, int type, long seconds, long nanoseconds);
      

      native 方法:

      frameworks/base/services/jni/com_android_server_AlarmManagerService.cpp
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      
      static void android_server_AlarmManagerService_set(JNIEnv* env, jobject obj, jint fd, jint type, jlong seconds, jlong nanoseconds)
      {
          struct timespec ts;
          ts.tv_sec = seconds;
          ts.tv_nsec = nanoseconds;
      
          int result = ioctl(fd, ANDROID_ALARM_SET(type), &ts);
          if (result < 0)
          {
              ALOGE("Unable to set alarm to %lld.%09lld: %s\n", seconds, nanoseconds, strerror(errno));
          }
      }
      

      fd 從哪里來的?AlarmManagerService 初始化來的:

      frameworks/services/java/com/android/server/AlarmManagerService.java
      1
      2
      3
      4
      5
      6
      
       public AlarmManagerService(Context context) {
              mContext = context;
              mDescriptor = init();
              mNextWakeup = mNextNonWakeup = 0;
              ...
          }
      

      init 是 native 方法:

      frameworks/base/services/jni/com_android_server_AlarmManagerService.cpp
      1
      2
      3
      4
      
      static jint android_server_AlarmManagerService_init(JNIEnv* env, jobject obj)
      {
          return open("/dev/alarm", O_RDWR);
      }
      

      在設(shè)下 alarm 之后, AlarmManagerService 啟動了一個 AlarmThread 來等待 alarm 的事件。

      frameworks/services/java/com/android/server/AlarmManagerService.java
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      
       private final AlarmThread mWaitThread = new AlarmThread();
      
       public AlarmManagerService(Context context) {
               ...
               if (mDescriptor != -1) {
                  mWaitThread.start();
              } else {
                  Slog.w(TAG, "Failed to open alarm driver. Falling back to a handler.");
              }
          }
      

      這個 AlarmThread 就會循環(huán)等待 alarm 事件!

      frameworks/services/java/com/android/server/AlarmManagerService.java
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      
        private class AlarmThread extends Thread
          {
              public AlarmThread()
              {
                  super("AlarmManager");
              }
      
              public void run()
              {
                  ArrayList<Alarm> triggerList = new ArrayList<Alarm>();
      
                  while (true)
                  {
                      int result = waitForAlarm(mDescriptor);
                      ...
                  }
              }
          }
      

      等到設(shè)定的時間到了的時候, AlarmManagerService 就會收到消息,發(fā)送當(dāng)初設(shè)定的 PendingIntent.

      這樣就滿足了設(shè)定特定時間提醒的功能。

      對于像鐘表這樣的程序,就需要一種機(jī)制,幾乎是時時的告訴,當(dāng)前是什么時間,而且要每一秒都要更新。這個需求怎么滿足呢?

      Android 的設(shè)計中有一個 Intent 是標(biāo)識這種時間改變的,但是不是每秒,是每分鐘啊 ?。?/p>

      Intent.java
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      
      /**  
       * Broadcast Action: The current time has changed.  Sent every
       * minute.  You can <em>not</em> receive this through components declared
       * in manifests, only by explicitly registering for it with
       * {@link Context#registerReceiver(BroadcastReceiver, IntentFilter)
       * Context.registerReceiver()}.
       *
       * <p class="note">This is a protected intent that can only be sent
       * by the system.
       */
      @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
      public static final String ACTION_TIME_TICK = "android.intent.action.TIME_TICK";
      

      你只要注冊了這個 Intent , 每分鐘開始的時候都會受到這個 Intent。AlarmManagerService 是如何提供這個服務(wù)的呢?

      在 AlarmManagerService 的構(gòu)造函數(shù)中會創(chuàng)建一個 ClockReceiver, 并在 scheduleTimeTickEvent 中調(diào)用native set 方法設(shè)置一個一分鐘后的時間提醒,設(shè)置的 PendingIntent 就是 ACTION_TIME_TICK 這個 Intent。

      而且,這個 ClockReceiver 還注冊了ACTION_TIME_TICK 的監(jiān)聽。一分鐘后它自己也會收到 ACTION_TIME_TICK,收到之后,它又調(diào)用了一次 scheduleTimeTickEvent,設(shè)定了下一分鐘的提醒。如是,每分鐘都會可以收到這個提醒了!

      frameworks/services/java/com/android/server/AlarmManagerService.java
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      
        public AlarmManagerService(Context context) {
              ...
      
              mTimeTickSender = PendingIntent.getBroadcastAsUser(context, 0,
                      new Intent(Intent.ACTION_TIME_TICK).addFlags(
                              Intent.FLAG_RECEIVER_REGISTERED_ONLY
                              | Intent.FLAG_RECEIVER_FOREGROUND), 0,
                              UserHandle.ALL);
              // now that we have initied the driver schedule the alarm
              mClockReceiver= new ClockReceiver();
              mClockReceiver.scheduleTimeTickEvent();
              ...
      
          }
      
         class ClockReceiver extends BroadcastReceiver {
              public ClockReceiver() {
                  IntentFilter filter = new IntentFilter();
                  filter.addAction(Intent.ACTION_TIME_TICK);
                  filter.addAction(Intent.ACTION_DATE_CHANGED);
                  mContext.registerReceiver(this, filter);
              }
             public void onReceive(Context context, Intent intent) {
                  if (intent.getAction().equals(Intent.ACTION_TIME_TICK)) {
                      scheduleTimeTickEvent();
              }
      
            public void scheduleTimeTickEvent() {
                  final long currentTime = System.currentTimeMillis();
                  final long nextTime = 60000 * ((currentTime / 60000) + 1);
      
                  // Schedule this event for the amount of time that it would take to get to
                  // the top of the next minute.
                  final long tickEventDelay = nextTime - currentTime;
      
                  final WorkSource workSource = null; // Let system take blame for time tick events.
                  set(ELAPSED_REALTIME, SystemClock.elapsedRealtime() + tickEventDelay, 0,
                          0, mTimeTickSender, true, workSource);
              }
          }
      

      可是這樣的話,每秒鐘的提醒它肯定滿足不了,那么時鐘是如何實(shí)現(xiàn)秒針的現(xiàn)實(shí)的呢?

      packages/apps/DeskClock/src/com/android/deskclock/AnalogClock.java
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      
          protected void onAttachedToWindow() {
           ...
           // tick the seconds
           post(mClockTick);
           ...
          }
      
          private final Runnable mClockTick = new Runnable () {
      
              @Override
              public void run() {
                  onTimeChanged();
                  invalidate();
                  AnalogClock.this.postDelayed(mClockTick, 1000);
              }
          };
      

      在創(chuàng)建的時候 post 一個 Runnable, 在 Runnable 中的 run 方法中 又設(shè)定了在一秒鐘之后,再 post 這個 Runnable。這樣每秒鐘都會執(zhí)行 Runnable 一次,進(jìn)行重新繪制。

      DeskClock 中的 widget 插件和應(yīng)用里面第二個 TAB 中的數(shù)字時鐘都是使用 TextClock, TextClock 也是監(jiān)聽 ACTION_TIME_TICK 來完成每分鐘的更新的。參考代碼:

      • frameworks/base/core/java/android/widget/TextClock.java

      Statusbar 上的 Clock 也是監(jiān)聽 ACTION_TIME_TICK 來完成每分鐘的更新的。參考代碼:

      • frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java

      Keyguard 上的 Clock 顯示也是使用的 TextClock 同上 。

      對于分鐘這個精度的時間顯示都可以使用監(jiān)聽 ACTION_TIME_TICK 的方式來完成。但是收到這個 Intent 的時候并沒有將當(dāng)前的時間傳遞過來,所以還是需要另外的接口來完成獲取當(dāng)前準(zhǔn)確時間的需求。

      獲取當(dāng)前 UTC 時間是通過 System.currentTimeMillis() 來完成的。

      libcore/luni/src/main/java/java/lang/System.java
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      
      /** 
       * Returns the current time in milliseconds since January 1, 1970 00:00:00.0 UTC.
       *
       * <p>This method always returns UTC times, regardless of the system's time zone.
       * This is often called "Unix time" or "epoch time".
       * Use a {@link java.text.DateFormat} instance to format this time for display to a human.
       *
       * <p>This method shouldn't be used for measuring timeouts or
       * other elapsed time measurements, as changing the system time can affect
       * the results. Use {@link #nanoTime} for that.
       */
      public static native long currentTimeMillis();
      

      為什么定義 1970.1.1 開始呢?因?yàn)槟谴蟾攀荱nix誕生的時間。

      這個 native 方法調(diào)用 gettimeofday 來完成的:

      libcore/luni/src/main/native/java_lang_System.cpp
      1
      2
      3
      4
      5
      6
      
      static jlong System_currentTimeMillis(JNIEnv*, jclass) {
          timeval now;
          gettimeofday(&now, NULL);
          jlong when = now.tv_sec * 1000LL + now.tv_usec / 1000;
          return when;
      }
      

      在 Linux shell 環(huán)境下輸入 man gettimeofday 獲取更多信息:

      libcore/luni/src/main/native/java_lang_System.cpp
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      
      GETTIMEOFDAY(2)                                      Linux Programmer's Manual                                     GETTIMEOFDAY(2)
      
      NAME
             gettimeofday, settimeofday - get / set time
      
      SYNOPSIS
             #include <sys/time.h>
      
             int gettimeofday(struct timeval *tv, struct timezone *tz);
             int settimeofday(const struct timeval *tv, const struct timezone *tz);
      
         Feature Test Macro Requirements for glibc (see feature_test_macros(7)):
      
             settimeofday(): _BSD_SOURCE
      
      DESCRIPTION
             The  functions  gettimeofday()  and  settimeofday()  can  get and set the time as well as a timezone.  The tv argument is a
             struct timeval (as specified in <sys/time.h>):
      
                 struct timeval {
                     time_t      tv_sec;     /* seconds */
                     suseconds_t tv_usec;    /* microseconds */
                 };
      
             and gives the number of seconds and microseconds since the Epoch (see time(2)).  The tz argument is a struct timezone:
      
                 struct timezone {
                     int tz_minuteswest;     /* minutes west of Greenwich */
                     int tz_dsttime;         /* type of DST correction */
                 };
      
             If either tv or tz is NULL, the corresponding structure is not set or returned.
      

      timeval 帶有兩個成員, tv_sec 保存秒數(shù),tv_usec 保存微秒(1/1000000 秒).可以看到上面 timeval 到毫秒的轉(zhuǎn)化 :

      libcore/luni/src/main/native/java_lang_System.cpp
      1
      
      jlong when = now.tv_sec * 1000LL + now.tv_usec / 1000;
      

      gettimeofday的實(shí)現(xiàn)是經(jīng) libc 進(jìn)入內(nèi)核,實(shí)際上是一個 system call 。詳情參考 kernel 的代碼。

      關(guān)于 libc 和 內(nèi)核的實(shí)現(xiàn)關(guān)系,我需要學(xué)習(xí)后再來討論,可以參考下 user space and libc interface

      獲取系統(tǒng)已經(jīng)運(yùn)行的時間有幾個不同的 API , 都在 SystemClock.java 中:

      • elapsedRealtime () //Returns milliseconds since boot, including time spent in sleep.
      • elapsedRealtimeNanos () //Returns nanoseconds since boot, including time spent in sleep.
      • uptimeMillis () //Returns milliseconds since boot, not counting time spent in deep sleep.

      elapsedRealtime()elapsedRealtimeNanos() 包含系統(tǒng) sleep 的時間,而 uptimeMillis() 不包含 sleep 的時間。參考 SystemClock

      elapsedRealtime() api 用的比較多,Android 系統(tǒng)里面 Settings->About phone->Status->Uptime 顯示的就是這個時間。Settings->Battery 顯示的時間也是用這個時間計算出來的(減去上一次 unplug 的時間)。

      來看下 elapsedRealtime 的底層實(shí)現(xiàn):

      SystemClock.java
      1
      
       native public static long elapsedRealtime();
      

      在 SystemClock 里用的是 native 的方法。

      frameworks/base/core/jni/android_os_SystemClock.cpp
      1
      2
      3
      4
      5
      6
      7
      8
      
      /*
       * native public static long elapsedRealtime();
       */
      static jlong android_os_SystemClock_elapsedRealtime(JNIEnv* env,
              jobject clazz)
      {
          return (jlong)elapsedRealtime();
      }
      

      cpp 中調(diào)用了libutils 中的方法 elapsedRealtime().

      system/core/libutils/SystemClock.cpp
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      
      /*
       * native public static long elapsedRealtime();
       */
      int64_t elapsedRealtime()
      {
          return nanoseconds_to_milliseconds(elapsedRealtimeNano());
      }
      
      ->
      
      /*
       * native public static long elapsedRealtimeNano();
       */
      int64_t elapsedRealtimeNano()
      {
      ...
          static int s_fd = -1;
      
          if (s_fd == -1) {
              int fd = open("/dev/alarm", O_RDONLY);
              if (android_atomic_cmpxchg(-1, fd, &s_fd)) {
                  close(fd);
              }
          }
      
          result = ioctl(s_fd,
                  ANDROID_ALARM_GET_TIME(ANDROID_ALARM_ELAPSED_REALTIME), &ts);
      
          if (result == 0) {
              timestamp = seconds_to_nanoseconds(ts.tv_sec) + ts.tv_nsec;
              checkTimeStamps(timestamp, &prevTimestamp, &prevMethod, METHOD_IOCTL);
              return timestamp;
          }
      ...
      }
      

      和鬧鐘的提醒功能相似,elapsedRealtimeNano() 也是通過 /dev/alarm 的 ioctl 來完成的,具體的實(shí)現(xiàn)要參看 driver 的代碼了。

      好了,獲取當(dāng)前時間(UTC)通過 kernel system call 完成, 獲取系統(tǒng)運(yùn)行時間通過 ioctl /dev/alarm 來完成。

      Alarm/Clock 系統(tǒng)還需要提供的一個功能是設(shè)置/同步時間。由于手機(jī)芯片中缺少一個斷電之后能繼續(xù)維持時間的模塊,所以,拔掉電池之后再開機(jī)之后時間會出現(xiàn)偏差(如果沒有同步或手動設(shè)置時間)。

      在 Android 系統(tǒng)中, Settings-> Date & Time –> 提供了設(shè)置時間和同步時間的UI 接口。 Date 和 Time 的設(shè)置都是使用 AlarmManagerService 提供的 setTime 接口。

      AlarmManagerService.java
      1
      2
      3
      4
      5
      6
      7
      
      public void setTime(long millis) {
          mContext.enforceCallingOrSelfPermission(
                  "android.permission.SET_TIME",
                  "setTime");  //檢查 permission
      
          SystemClock.setCurrentTimeMillis(millis);
      }
      

      AlarmManagerService 調(diào)用了 SystemClock 的 api setCurrentTimeMillis.

      SystemClock.java
      1
      2
      3
      4
      5
      6
      7
      
      /** 
       * Sets the current wall time, in milliseconds.  Requires the calling
       * process to have appropriate permissions.
       *
       * @return if the clock was successfully set to the specified time.
       */
      native public static boolean setCurrentTimeMillis(long millis);
      

      SystemClock.java 調(diào)用了 native 方法

      android_os_SystemClock.cpp
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      
      /*
       * Set the current time.  This only works when running as root.
       */
      static int setCurrentTimeMillis(int64_t millis)
      {
      
      ...
          fd = open("/dev/alarm", O_RDWR);
      ...
          res = ioctl(fd, ANDROID_ALARM_SET_RTC, &ts);
      ...
      }
      

      android_os_SystemClock.cpp 是直接利用 ioctl /dev/alarm 調(diào)用到 driver 的 alarm 來完成。

      同步時間的功能是定期的從 Google 的服務(wù)器 2.android.pool.ntp.org (默認(rèn)配置) 獲取時間,刷新的時間間隔有兩種,一種長的是 24 h,一種短的是 60s。

      參考代碼:

      • frameworks/base/services/java/com/android/server/NetworkTimeUpdateService.java
      • frameworks/base/core/java/android/util/NtpTrustedTime.java
      • frameworks/base/core/res/res/values/config.xml

      通過 ioctl /dev/alarm 操組 driver 的 alarm 模塊來完成設(shè)置時間,通過定期和 Google 服務(wù)器 2.android.pool.ntp.org 同步來完成時間的同步。

        本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報。
        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評論

        發(fā)表

        請遵守用戶 評論公約

        類似文章 更多